C# 是否使用实体框架执行自定义sql?
我需要执行一个customquery,它将保存在数据库的某个地方,我需要它返回到datatable或dataset中,并将其绑定到一个gridview,该gridview将自动生成列为trueC# 是否使用实体框架执行自定义sql?,c#,entity-framework,entity-framework-4,ado.net,C#,Entity Framework,Entity Framework 4,Ado.net,我需要执行一个customquery,它将保存在数据库的某个地方,我需要它返回到datatable或dataset中,并将其绑定到一个gridview,该gridview将自动生成列为true 我所有的数据访问层都可以完美地使用entity framework,但对于某些特定场景,我需要这样做,我想知道是否应该将ado.net与entity framework结合起来,或者EF是否可以以某种方式实现这一点,如果您的目标是返回ado.net结构(DataTable或DataSet),那么只需使用经
我所有的数据访问层都可以完美地使用entity framework,但对于某些特定场景,我需要这样做,我想知道是否应该将ado.net与entity framework结合起来,或者EF是否可以以某种方式实现这一点,如果您的目标是返回ado.net结构(DataTable或DataSet),那么只需使用经典的ado.net即可。您会发现,这比尝试将数据绑定到实体集,然后自己填充数据表或数据集更容易 但是,如果您确实对通过EntityFramework运行自定义查询感兴趣,请看一看。它允许您执行SQL查询并将结果映射回模型中的实体。然后,获取IEnumerable结果并将其映射到DataTable或DataSet将是您的一项练习。因此,我最初的回答是“只需使用好的ol’风格的ADO.NET方法即可。”对于实体框架5使用 context.Database.SqlQuery
对于实体框架4,请使用以下代码 context.ExecuteStoreQuery
公共字符串BuyerSequenceNumberMax(int-buyerId)
{
string sequenceMaxQuery=“从BuyerTakenItemToSale btitosal中选择TOP(1)btitosal.BuyerSequenceNumber”+
“其中btitosal.BuyerID=“+BuyerID+
“按转换顺序(INT,子字符串(btitosal.BuyerSequenceNumber,7,LEN(btitosal.BuyerSequenceNumber)))描述”;
var sequenceQueryResult=context.Database.SqlQuery(sequenceMaxQuery).FirstOrDefault();
string buyerSequenceNumber=string.Empty;
if(sequenceQueryResult!=null)
{
buyerSequenceNumber=sequenceQueryResult.ToString();
}
返回买方序列号;
}
要返回列表,请使用以下代码
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();
}
公共列表面板SerialByLocation和Stock(字符串位置代码、字节存储位置、字符串项目类别、字符串项目容量、字节协议类型、字符串包代码)
{
string panelSerialByLocationAndStockQuery=“选择isws.ItemSerialNo,im.ItemModel”+
“来自Inv_ItemMaster im”+
“内部联接”+
“Inv_ItemStockwith SerialNobyLocation isws”+
“在im.ItemCode=isws.ItemCode上”+
“其中isws.LocationCode='”+LocationCode+“'和”+
“isws.StoreLocation=“+StoreLocation+”和”+
“isws.IsAvailableInStore=1和”+
“im.ItemCapacity='”+ItemCapacity+“'和”+
“isws.ItemSerialNo不在(”+
“从特殊包装价格中选择sp.PanelSerialNo用于转售sp”+
“其中sp.PackageCode=”“+PackageCode+”)”;
context.Database.SqlQuery(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连接执行查询
当我们动态地做一些事情或者当我们不能映射到一个实体时,这将非常有用。例如,我们可以在数据表中获取内容
上面的语法是针对EF5.0的。我使用EF6,有一天我需要一种方法来执行动态SQL字符串并获取数据表。首先,我只是将
DbContext.Database.Connection
转换为SqlConnection
,并完成了整个工作。它在测试中起作用,但应用程序被破坏了,因为我们使用的scape将DbConnection
的自我实现注入了类型scape.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
的测试,以及scape.Ado.AlternateType.GlimpseDbConnection
如果您不确定是否已清除所有输入,使用SQL参数防止SQL注入攻击。如果调用返回多个结果集的存储过程,则不支持MARS?SqlQuery意味着每次调用只能处理一种类型的结果集。
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);
}
}