我需要执行一个自定义查询,它将保存在数据库的某个地方,我需要它返回一个数据表或数据集,并将其绑定到一个gridview,它将自动生成列为true。与实体框架执行自定义的SQL?
我所有的数据访问层可以完美兼容实体框架,但对于一些特定情况下,我需要做到这一点,我不知道我是否应该与实体框架结合ado.net,或者EF能做到它在某种程度上
我需要执行一个自定义查询,它将保存在数据库的某个地方,我需要它返回一个数据表或数据集,并将其绑定到一个gridview,它将自动生成列为true。与实体框架执行自定义的SQL?
我所有的数据访问层可以完美兼容实体框架,但对于一些特定情况下,我需要做到这一点,我不知道我是否应该与实体框架结合ado.net,或者EF能做到它在某种程度上
如果您的目标是返回ADO.NET结构(DataTable或DataSet),那么只需使用经典的ADO.NET。你会发现它比试图将数据绑定到实体集然后自己填充DataTable或DataSet更简单。
但是,如果您真的有兴趣通过EntityFramework运行自定义查询,请查看ExecuteQuery。它允许您执行SQL查询并将结果映射回模型中的实体。这将是你的一部分练习IEnumerable结果并将其映射到DataTable或DataSet。因此,我最初的回答是“只用好的ADO.NET方法来做”。
对于实体框架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();
}
这里是另一个层面和更简单的方法。使用实体框架上下文获取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注入了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.Connection
是SqlConnection
和Glimpse.Ado.AlternateType.GlimpseDbConnection
如果你不知道你已经消毒所有的输入,使用SQL参数来防止SQL注入攻击。 –