Pregunta

Estoy trabajando con un sistema que tiene muchos procedimientos almacenados que se deben mostrar. La creación de entidades para cada uno de mis objetos no es práctico.

¿Es posible y cómo tendría que devolver una DataTable usando 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;
}
¿Fue útil?

Solución

No, no creo que se va a trabajar. - Marco de la entidad está orientada a devolver entidades y no está destinado a objetos de retorno DataTable

Si necesita DataTable objetos, utilizar ADO.NET recta en su lugar.

Otros consejos

Sí, es posible, pero se debe utilizar para conjunto de resultados simplemente dinámico o SQL prima.

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

Edit: Es mejor utilizar ADO.NET clásico para obtener el modelo de datos en lugar de utilizar Marco de la entidad porque la mayoría probablemente no se puede utilizar DataTable incluso si se puede ejecutar el método: context.ExecuteStoreQuery<DataTable>(commandText, parameters).FirstOrDefault();

ADO.NET Ejemplo:

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;
}

Este método utiliza la cadena de conexión desde el marco de la entidad para establecer una conexión ADO.NET, a una base de datos MySQL en este ejemplo.

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;
}

Sí, se puede hacer fácilmente de esta manera:

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());
}

Por la regla, no debe utilizar un conjunto de datos dentro de una aplicación EF. Pero, si realmente necesita (por ejemplo, para alimentar un informe), que la solución debe trabajar (que de EF 6 Código):

    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's 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;
    }

La forma más fácil de devolver un DataTable utilizando el ADO.NET Entity Framework es hacer lo siguiente:

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

Por ejemplo:

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

Tal vez el procedimiento almacenado puede devolver un tipo de complejo? http: // blogs .msdn.com / b / Somasegar / archivo / 2010/01/11 / entidad-marco-en-red-4.aspx

En mi solución basada Entity Framework tengo que sustituir uno de mis consultas LINQ con SQL - por razones de eficiencia. También quiero mis resultados en un DataTable de un procedimiento almacenado para que pudiera crear un parámetro de valor de la tabla a pasar a un segundo procedimiento almacenado. Por lo tanto:

  1. Estoy usando SQL

  2. No quiero un DataSet

  3. Iterar una IEnumerable probablemente no se va a cortar - por razones de eficiencia

Además, yo estoy usando EF6, por lo que yo preferiría DbContext.SqlQuery sobre ObjectContext.ExecuteStoreQuery como el cartel original solicitado.

Sin embargo, he encontrado que esto simplemente no funcionó:

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

Esta es mi solución. Devuelve un DataTable se descargará y utilizando un SqlDataReader ADO.NET - que creo que es más rápido que un SqlDataAdapter en los datos de sólo lectura. No responde estrictamente a la cuestión, ya que utiliza ADO.Net, pero muestra cómo hacerlo después de conseguir un asimiento de la conexión desde el 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;
        }
    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top