用entity framework执行自定义sql?
我需要执行一个自定义查询,它将被保存在数据库中的某个地方,我需要它返回数据表或数据集并将其绑定到gridview,它将自动生成列为true。
我的所有数据访问层都与entity framework完美配合,但对于某些特定场景,我需要这样做,我想知道我是否应该将ado.net与entity framework结合起来,或者如果EF能够以某种方式实现它
如果您的目标是返回ADO.NET结构(DataTable或DataSet),那么只需使用经典的ADO.NET即可。 您会发现它比尝试将数据绑定到实体集然后自己填充DataTable或DataSet更容易。
但是,如果您真的真的有兴趣通过EntityFramework运行自定义查询,请查看ExecuteQuery 。 它允许您执行SQL查询并将结果映射回模型中的实体。 然后,您将获取IEnumerable结果并将其映射到DataTable或DataSet。 因此,我原来的答案是“用好的OL’方式做ADO.NET方法。”
对于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(sequenceMaxQuery).FirstOrDefault(); string buyerSequenceNumber = string.Empty; if (sequenceQueryResult != null) { buyerSequenceNumber = sequenceQueryResult.ToString(); } return buyerSequenceNumber; }
对于Return a List,请使用以下代码
public List 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 (panelSerialByLocationAndStockQuery).ToList(); }
这是另一个维度和更简单的方法。 使用您的entity framework获取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 。
我使用EF6,有一天我需要执行动态SQL字符串并获取DataTable。 首先,我只是将DbContext.Database.Connection
为SqlConnection
并完成整个工作。 它适用于测试,但是应用程序被破坏了,因为我们使用的Glimpse使用类型Glimpse.Ado.AlternateType.GlimpseDbConnection
注入DbConnection
自我实现。 我需要独立于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.Connection
是SqlConnection
和Glimpse.Ado.AlternateType.GlimpseDbConnection