Returning a DataTable using Entity Framework ExecuteStoreQuery

前端 未结 8 1376
清酒与你
清酒与你 2020-12-09 04:28

I am working with a system that has many stored procedures that need to be displayed. Creating entities for each of my objects is not practical.

Is it possible and

相关标签:
8条回答
  • 2020-12-09 05:02

    In my Entity Framework based solution I need to replace one of my Linq queries with sql - for efficiency reasons. Also I want my results in a DataTable from one stored procedure so that I could create a table value parameter to pass into a second stored procedure. So:

    1. I'm using sql

    2. I don't want a DataSet

    3. Iterating an IEnumerable probably isn't going to cut it - for efficiency reasons

    Also, I am using EF6, so I would prefer DbContext.SqlQuery over ObjectContext.ExecuteStoreQuery as the original poster requested.

    However, I found that this just didn't work:

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

    This is my solution. It returns a DataTable that is fetched using an ADO.NET SqlDataReader - which I believe is faster than a SqlDataAdapter on read-only data. It doesn't strictly answer the question because it uses ADO.Net, but it shows how to do that after getting a hold of the connection from the 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;
            }
        }
    
    0 讨论(0)
  • 2020-12-09 05:04

    Yes it can easily be done like this:

    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());
    }
    
    0 讨论(0)
  • 2020-12-09 05:09

    The easiest way to return a DataTable using the EntityFramework is to do the following:

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

    For example:

    MetaTable metaTable = Global.DefaultModel.GetTable("Employees");
    
    0 讨论(0)
  • 2020-12-09 05:13

    No, I don't think that'll work - Entity Framework is geared towards returning entities and isn't meant to return DataTable objects.

    If you need DataTable objects, use straight ADO.NET instead.

    0 讨论(0)
  • 2020-12-09 05:13

    Yes it's possible, but it should be used for just dynamic result-set or raw SQL.

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

    Edit: It's better to use classical ADO.NET to get the data model rather than using Entity Framework because most probably you cannot use DataTable even if you can run the method: context.ExecuteStoreQuery<DataTable>(commandText, parameters).FirstOrDefault();

    ADO.NET Example:

    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;
    }
    
    0 讨论(0)
  • 2020-12-09 05:13

    By the rule, you shouldn't use a DataSet inside a EF application. But, if you really need to (for instance, to feed a report), that solution should work (it's EF 6 code):

        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;
        }
    
    0 讨论(0)
提交回复
热议问题