使用Entity Framework执行自定义SQL?

12

我需要执行一个自定义查询并将其保存到数据库中,然后返回一个datatable或dataset,并将其绑定到一个autogenerate列为true的gridview。

我的数据访问层与entity framework完全兼容,但对于某些特定情况,我需要这样做,我想知道是否应该结合ado.net和entity framework,或者EF是否可以以某种方式完成它。

4个回答

20

对于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();


}

11
如果您不确定是否已经对所有输入进行了处理,请使用SQL参数来防止SQL注入攻击。 - Edward Brey
如果调用返回多个结果集的存储过程,则不支持MARS。SqlQuery<T>意味着每次调用只能处理单个类型的结果集。 - Triynko

12

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

使用您的实体框架上下文获取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


9

如果您的目标是返回 ADO.NET 结构(DataTable 或 DataSet),那么只需使用经典的 ADO.NET 即可。这比尝试将数据绑定到实体集并手动填充 DataTable 或 DataSet 要更容易。

然而,如果您真正想运行通过 EntityFramework 运行定制查询,请查看 ExecuteQuery。它允许您执行 SQL 查询并将结果映射回模型中的实体。然后,您需要自己将 IEnumerable 结果映射到 DataTable 或 DataSet。因此,我最初的答案是“请使用经典的 ADO.NET 方法”。


3

我使用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.ConnectionSqlConnection 的测试,以及对于 Glimpse.Ado.AlternateType.GlimpseDbConnection

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接