Richard Deeming
Вот решение для Entity Framework 6, собранное из нескольких постов StackOverflow:
c# - возврат datatable с помощью entity framework - переполнение стека[^] - не работает с параметризованными запросами;
Как я могу получить параметры запроса Entity Framework? - переполнение стека[^] - показывает, как получить доступ к параметрам запроса;
using System;
using System.Data;
using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.Core.EntityClient;
using System.Data.Entity.Core.Objects;
using System.Data.Entity.Infrastructure;
namespace EntityFramework
{
public static class DbContextExtensions
{
private static class ReflectionCache<T>
{
public static readonly PropertyInfo InternalQuery = typeof(DbQuery<T>).GetProperty("InternalQuery", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
}
public static ObjectQuery<T> GetObjectQuery<T>(this IQueryable<T> source)
{
if (source is null) throw new ArgumentNullException(nameof(source));
if (!(source is DbQuery<T> query)) throw new NotSupportedException();
var internalQuery = ReflectionCache<T>.InternalQuery.GetValue(query, null);
var objectQueryProperty = internalQuery.GetType().GetProperty("ObjectQuery", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
return (ObjectQuery<T>)objectQueryProperty.GetValue(internalQuery, null);
}
private static DbCommand ToDbCommand<T>(IQueryable<T> source, out DbProviderFactory dbFactory)
{
if (source is null) throw new ArgumentNullException(nameof(source));
var objectQuery = source.GetObjectQuery();
var connection = objectQuery.Context.Connection;
if (connection is EntityConnection ec) connection = ec.StoreConnection;
dbFactory = DbProviderFactories.GetFactory(connection);
var command = dbFactory.CreateCommand();
command.Connection = connection;
command.CommandType = CommandType.Text;
command.CommandText = objectQuery.ToTraceString();
foreach (var parameter in objectQuery.Parameters)
{
var dbParameter = command.CreateParameter();
dbParameter.ParameterName = parameter.Name;
dbParameter.Value = parameter.Value;
command.Parameters.Add(dbParameter);
}
return command;
}
public static DbCommand ToDbCommand<T>(this IQueryable<T> source)
{
return ToDbCommand(source, out _);
}
public static DataTable ToDataTable<T>(this IQueryable<T> source)
{
if (source is null) throw new ArgumentNullException(nameof(source));
using (var command = ToDbCommand(source, out var dbFactory))
using (var adapter = dbFactory.CreateDataAdapter())
{
adapter.SelectCommand = command;
var dt = new DataTable();
adapter.Fill(dt);
return dt;
}
}
}
}
С этим вспомогательным классом на месте ваш код становится:
public DataTable Excels()
{
var employeeInf = myentities.Employee.Select(x => new
{
x.ID,
x.Name,
x.Surname,
x.Branch
}); // NB: No "ToList" call here.
return employeeInf.ToDataTable();
}