Подтвердить что ты не робот

Возврат DataTable с использованием Entity Framework ExecuteStoreQuery

Я работаю с системой, в которой есть много хранимых процедур, которые необходимо отобразить. Создание объектов для каждого из моих объектов нецелесообразно.

Возможно ли это и как вернуть DataTable с помощью ExecuteStoreQuery?

public ObjectResult<DataTable> MethodName(string fileSetName) {
using (var dataContext = new DataContext(_connectionString))
{
var returnDataTable = ((IObjectContextAdapter)dataContext).ObjectContext.ExecuteStoreQuery<DataTable>("SP_NAME","SP_PARAM");
return returnDataTable;
}
4b9b3361

Ответ 1

Нет, я не думаю, что это сработает. Entity Framework ориентирован на возвращение объектов и не предназначен для возврата объектов DataTable.

Если вам нужны объекты DataTable, используйте вместо этого прямой ADO.NET.

Ответ 2

Да, это возможно, но оно должно использоваться только для динамического набора результатов или необработанного SQL.

public DataTable ExecuteStoreQuery(string commandText, params Object[] parameters)
{
    DataTable retVal = new DataTable();
    retVal = context.ExecuteStoreQuery<DataTable>(commandText, parameters).FirstOrDefault();
    return retVal;
}

Изменить: лучше использовать классический ADO.NET для получения модели данных, а не для использования Entity Framework, потому что, скорее всего, вы не можете использовать DataTable, даже если вы можете запустить метод: context.ExecuteStoreQuery<DataTable>(commandText, parameters).FirstOrDefault();

Пример ADO.NET:

public DataSet GetResultReport(int questionId)
{
    DataSet retVal = new DataSet();
    EntityConnection entityConn = (EntityConnection)context.Connection;
    SqlConnection sqlConn = (SqlConnection)entityConn.StoreConnection;
    SqlCommand cmdReport = new SqlCommand([YourSpName], sqlConn);
    SqlDataAdapter daReport = new SqlDataAdapter(cmdReport);
    using (cmdReport)
    {
        SqlParameter questionIdPrm = new SqlParameter("QuestionId", questionId);
        cmdReport.CommandType = CommandType.StoredProcedure;
        cmdReport.Parameters.Add(questionIdPrm);
        daReport.Fill(retVal);
    }
    return retVal;
}

Ответ 3

Этот метод использует строку соединения из фреймворка сущности для установления соединения ADO.NET с базой данных MySQL в этом примере.

using MySql.Data.MySqlClient;

public DataSet GetReportSummary( int RecordID )
{
    var context = new catalogEntities();

    DataSet ds = new DataSet();
    using ( MySqlConnection connection = new MySqlConnection( context.Database.Connection.ConnectionString ) )
    {
        using ( MySqlCommand cmd = new MySqlCommand( "ReportSummary", connection ) )
        {
            MySqlDataAdapter adapter = new MySqlDataAdapter( cmd );
            adapter.SelectCommand.CommandType = CommandType.StoredProcedure;
            adapter.SelectCommand.Parameters.Add( new MySqlParameter( "@ID", RecordID ) );
            adapter.Fill( ds );
        }
    }
    return ds;
}

Ответ 4

По правилу вы не должны использовать DataSet внутри приложения EF. Но если вам действительно нужно (например, подать отчет), это решение должно работать (это код EF 6):

    DataSet GetDataSet(string sql, CommandType commandType, Dictionary<string, Object> parameters)
    {
        // creates resulting dataset
        var result = new DataSet();

        // creates a data access context (DbContext descendant)
        using (var context = new MyDbContext())
        {
            // creates a Command 
            var cmd = context.Database.Connection.CreateCommand();
            cmd.CommandType = commandType;
            cmd.CommandText = sql;

            // adds all parameters
            foreach (var pr in parameters)
            {
                var p = cmd.CreateParameter();
                p.ParameterName = pr.Key;
                p.Value = pr.Value;
                cmd.Parameters.Add(p);
            }

            try
            {
                // executes
                context.Database.Connection.Open();
                var reader = cmd.ExecuteReader();

                // loop through all resultsets (considering that it possible to have more than one)
                do
                {
                    // loads the DataTable (schema will be fetch automatically)
                    var tb = new DataTable();
                    tb.Load(reader);
                    result.Tables.Add(tb);

                } while (!reader.IsClosed);
            }
            finally
            {
                // closes the connection
                context.Database.Connection.Close();
            }
        }

        // returns the DataSet
        return result;
    }

Ответ 5

Самый простой способ вернуть DataTable с помощью EntityFramework - сделать следующее:

MetaTable metaTable = Global.DefaultModel.GetTable("Your EntitySetName");

Например:

MetaTable metaTable = Global.DefaultModel.GetTable("Employees");

Ответ 7

В моем решении на основе Entity Framework мне нужно заменить один из моих запросов Linq на sql - по соображениям эффективности. Также я хочу, чтобы мои результаты были в DataTable из одной хранимой процедуры, чтобы я мог создать параметр значения таблицы, чтобы перейти во вторую хранимую процедуру. Итак:

  • Я использую sql

  • Я не хочу DataSet

  • Итерация IEnumerable, вероятно, не собирается сокращать ее - по соображениям эффективности

Кроме того, я использую EF6, поэтому я бы предпочел DbContext.SqlQuery over ObjectContext.ExecuteStoreQuery по запросу оригинального плаката.

Однако я обнаружил, что это просто не сработало:

_Context.Database.SqlQuery<DataTable>(sql, parameters).FirstOrDefault();

Это мое решение. Он возвращает DataTable, который извлекается с использованием ADO.NET SqlDataReader, который, я считаю, быстрее, чем SqlDataAdapter для данных только для чтения. Он не строго отвечает на вопрос, потому что он использует ADO.Net, но он показывает, как это сделать после получения связи из DbContext

    protected DataTable GetDataTable(string sql, params object[] parameters)
    {
        //didn't work - table had no columns or rows
        //return Context.Database.SqlQuery<DataTable>(sql, parameters).FirstOrDefault();

        DataTable result = new DataTable();
        SqlConnection conn = Context.Database.Connection as SqlConnection;
        if(conn == null)
        {
            throw new InvalidCastException("SqlConnection is invalid for this database");
        }
        using (SqlCommand cmd = new SqlCommand(sql, conn))
        {
            cmd.Parameters.AddRange(parameters);
            conn.Open();
            using (SqlDataReader reader = cmd.ExecuteReader())
            {
                result.Load(reader);
            }
            return result;
        }
    }

Ответ 8

Да, это можно сделать следующим образом:

var table = new DataTable();
using (var ctx = new SomeContext())
{
    var cmd = ctx.Database.Connection.CreateCommand();
    cmd.CommandText = "Select Col1, Col2 from SomeTable"; 

    cmd.Connection.Open();
    table.Load(cmd.ExecuteReader());
}