简体   繁体   中英

execute custom sql with entity framework?

I need to execute a customquery which wil be saved somewhere in the database and I need it to return in a datatable, or dataset and bind it to a gridview which will have autogenerate columns to true.

All my Data access layer works perfect with entity framework, but for some specific scenario I need to do this and I wonder if I should combine ado.net with entity framework, or if EF can do it somehow

For Entity Framework 5 use

context.Database.SqlQuery


And For Entity Framework 4 use the following code

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;
    }

For Return a List use the following Code

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


}

Here's another dimension and easier approach. Get SQL Connection using your Entity Framework Context:

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);
}

And we can use DataAdapter or any other classic method to execute queries using the EF connection.

This will be very useful when we do something dynamically and when we can't map to a Entity. We can get things in a DataTable for example.

The above Syntax is for EF 5.0 .

If your goal is to return ADO.NET structures (DataTable or DataSet), then just use classic ADO.NET. You'll find it easier than trying to bind data to an Entity set and then populating a DataTable or DataSet yourself.

However, if you're really and truly interested running a custom query through EntityFramework, take a look at ExecuteQuery . It allows you to execute a SQL Query and maps the result back to entities in your model. It would then be an exercise on your part to take the IEnumerable result and map it to a DataTable or DataSet. Hence my original answer of "just do it with good ol' fashioned ADO.NET methods."

I use EF6 and one day I needed way to execute dynamic SQL string and get DataTable. Firstly I merely cast DbContext.Database.Connection to SqlConnection and did whole job. It worked for tests, but application were broken, because Glimpse, that we use, injects self implementation of DbConnection with type Glimpse.Ado.AlternateType.GlimpseDbConnection . I need approach that works independently of what DbConnection is. Finally I end up with following code:

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);
        }
    }

And this works for any case: for tests where DbContext.Database.Connection is SqlConnection and for Glimpse.Ado.AlternateType.GlimpseDbConnection

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM