2012-06-05 27 views
8

我需要执行一个自定义查询,它将保存在数据库的某个地方,我需要它返回一个数据表或数据集,并将其绑定到一个gridview,它将自动生成列为true。与实体框架执行自定义的SQL?

我所有的数据访问层可以完美兼容实体框架,但对于一些特定情况下,我需要做到这一点,我不知道我是否应该与实体框架结合ado.net,或者EF能做到它在某种程度上

回答

8

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

但是,如果您真的有兴趣通过EntityFramework运行自定义查询,请查看ExecuteQuery。它允许您执行SQL查询并将结果映射回模型中的实体。这将是你的一部分练习IEnumerable结果并将其映射到DataTable或DataSet。因此,我最初的回答是“只用好的ADO.NET方法来做”。

16

对于实体框架5使用

context.Database.SqlQuery


实体框架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(); 


} 
+7

如果你不知道你已经消毒所有的输入,使用SQL参数来防止SQL注入攻击。 –

9

这里是另一个层面和更简单的方法。使用实体框架上下文获取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

2

我使用EF6,有一天我需要的方式来执行动态SQL字符串并获取DataTable。首先,我只是投了DbContext.Database.ConnectionSqlConnection,做了整个工作。它适用于测试,但是应用程序被破坏了,因为我们使用的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