【问题标题】:execute custom sql with entity framework?使用实体框架执行自定义 sql?
【发布时间】:2012-06-05 13:35:32
【问题描述】:

我需要执行一个自定义查询,该查询将保存在数据库中的某个位置,我需要它返回一个数据表或数据集,并将其绑定到一个网格视图,该网格视图将自动生成列为真。

我所有的数据访问层都可以与实体框架完美配合,但对于某些特定场景,我需要这样做,我想知道是否应该将 ado.net 与实体框架结合起来,或者 EF 是否可以以某种方式做到这一点

【问题讨论】:

    标签: c# entity-framework entity-framework-4 ado.net


    【解决方案1】:

    对于 Entity Framework 5 使用

    context.Database.SqlQuery


    对于 Entity Framework 4 使用以下代码

    context.ExecuteStoreQuery


     public string BuyerSequenceNumberMax(int buyerId)
        {
            string sequenceMaxQuery = "SELECT TOP(1) btitosal.BuyerSequenceNumber FROM BuyerTakenItemToSale btitosal " +
                                      "WHERE btitosal.BuyerID =  " + buyerId +
                                      "ORDER BY  CONVERT(INT,SUBSTRING(btitosal.BuyerSequenceNumber,7, LEN(btitosal.BuyerSequenceNumber))) DESC";
    
            var sequenceQueryResult = context.Database.SqlQuery<string>(sequenceMaxQuery).FirstOrDefault();
    
            string buyerSequenceNumber = string.Empty;
    
            if (sequenceQueryResult != null)
            {
                buyerSequenceNumber = sequenceQueryResult.ToString();
            }
    
            return buyerSequenceNumber;
        }
    

    要返回列表,请使用以下代码

     public List<PanelSerialList> PanelSerialByLocationAndStock(string locationCode, byte storeLocation, string itemCategory, string itemCapacity, byte agreementType, string packageCode)
     {
           string panelSerialByLocationAndStockQuery = "SELECT isws.ItemSerialNo,  im.ItemModel " +
            "FROM Inv_ItemMaster im   " +
            "INNER JOIN  " +
            "Inv_ItemStockWithSerialNoByLocation isws  " +
            "   ON im.ItemCode = isws.ItemCode   " +
            "       WHERE isws.LocationCode = '" + locationCode + "' AND  " +
            "   isws.StoreLocation = " + storeLocation + " AND  " +
            "   isws.IsAvailableInStore = 1 AND " +
            "   im.ItemCapacity = '" + itemCapacity + "' AND " +
            "   isws.ItemSerialNo NOT IN ( " +
            "           Select sp.PanelSerialNo From Special_SpecialPackagePriceForResale sp  " +
            "           Where sp.PackageCode = '" + packageCode + "' )";
    
    
    
        context.Database.SqlQuery<PanelSerialList>(panelSerialByLocationAndStockQuery).ToList();
    
    
    }
    

    【讨论】:

    • 如果您不确定是否已清理所有输入,请使用 SQL 参数来防止 SQL 注入攻击。
    • 如果调用返回多个结果集的存储过程,不支持 MARS? SqlQuery 意味着它每次调用只能处理一种类型的结果集。
    【解决方案2】:

    这是另一个维度和更简单的方法。使用您的实体框架上下文获取 SQL 连接:

    var connection = (System.Data.SqlClient.SqlConnection) _db.Database.Connection;
    
    if (connection != null && connection.State == ConnectionState.Closed)
    {
        connection.Open();
    }
    
    var dt = new DataTable();
    
    using (var com = new System.Data.SqlClient.SqlDataAdapter("Select * from Table", connection))
    {
        com.Fill(dt);
    }
    

    我们可以使用DataAdapter 或任何其他经典方法使用EF 连接执行查询。

    当我们动态地做某事并且我们不能映射到实体时,这将非常有用。例如,我们可以在 DataTable 中获取内容。

    上述语法适用于EF 5.0

    【讨论】:

      【解决方案3】:

      如果您的目标是返回 ADO.NET 结构(DataTable 或 DataSet),那么只需使用经典的 ADO.NET。您会发现这比尝试将数据绑定到实体集然后自己填充 DataTable 或 DataSet 更容易。

      但是,如果您真的有兴趣通过 EntityFramework 运行自定义查询,请查看ExecuteQuery。它允许您执行 SQL 查询并将结果映射回模型中的实体。然后,您可以练习获取 IEnumerable 结果并将其映射到 DataTable 或 DataSet。因此,我最初的回答是“只需使用良好的老式 ADO.NET 方法即可。”

      【讨论】:

        【解决方案4】:

        我使用 EF6,有一天我需要一种方法来执行动态 SQL 字符串并获取 DataTable。首先,我只是将DbContext.Database.Connection 转换为SqlConnection 并完成了整个工作。它适用于测试,但应用程序被破坏了,因为我们使用的 Glimpse 注入了 DbConnection 的自我实现,类型为 Glimpse.Ado.AlternateType.GlimpseDbConnection。我需要独立于 DbConnection 的方法。最后我得到以下代码:

        public class SqlDataProvider : ISqlDataProvider
        {
            private readonly DbContext _context;
        
            public SqlDataProvider(DbContext context)
            {
                _context = context;
            }
        
            public DataTable GetDataTable(string sqlQuery)
            {
                try
                {
                    DbProviderFactory factory = DbProviderFactories.GetFactory(_context.Database.Connection);
        
                    using (var cmd = factory.CreateCommand())
                    {
                        cmd.CommandText = sqlQuery;
                        cmd.CommandType = CommandType.Text;
                        cmd.Connection = _context.Database.Connection;
                        using (var adapter = factory.CreateDataAdapter())
                        {
                            adapter.SelectCommand = cmd;
        
                            var tb = new DataTable();
                            adapter.Fill(tb);
                            return tb;
                        }
                    }
               }
                catch (Exception ex)
                {
                    throw new SqlExecutionException(string.Format("Error occurred during SQL query execution {0}", sqlQuery), ex);
                }
            }
        

        这适用于任何情况:对于 DbContext.Database.ConnectionSqlConnectionGlimpse.Ado.AlternateType.GlimpseDbConnection 的测试

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-03-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多