Вопрос по entity-framework-4, entity-framework, ado.net, c# – выполнить пользовательский sql с сущностью Framework?

8

Мне нужно выполнить пользовательский запрос, который будет сохранен где-то в базе данных, и мне нужно, чтобы он вернулся в набор данных или набор данных и связал его с видом сетки, который будет автоматически генерировать столбцы в true.

Весь мой уровень доступа к данным отлично работает с Entity Framework, но для какого-то конкретного сценария мне нужно это сделать, и мне интересно, стоит ли мне комбинировать ado.net с Entity Framework или EF может это как-то сделать

Ваш Ответ

4   ответа
11

Здесь другое измерение и более легкий подход. Получите соединение SQL, используя ваш контекст Entity Framework:

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.

17

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


}
Нет поддержки MARS при вызове хранимой процедуры, которая возвращает несколько наборов результатов? SQLQuery & л; Т & GT; подразумевает, что он может обрабатывать только один тип набора результатов за вызов.
Если вы не уверены, что санировали все входные данные, используйте параметры SQL для предотвращения атак с использованием SQL-инъекций.
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.Connection являетсяSqlConnection и дляGlimpse.Ado.AlternateType.GlimpseDbConnection

8

Если ваша цель - вернуть структуры ADO.NET (DataTable или DataSet), просто используйте классический ADO.NET. Вы найдете это проще, чем пытаться связать данные с набором сущностей, а затем заполнить DataTable или DataSet самостоятельно.

Однако, если вы действительно заинтересованы в выполнении пользовательского запроса через EntityFramework, взгляните наExecuteQuery, Это позволяет вам выполнить SQL-запрос и отобразить результат обратно в сущности в вашей модели. Тогда с вашей стороны было бы упражнением взять IEnumerable результат и отобразить его в DataTable или DataSet. Следовательно, мой первоначальный ответ «просто сделай это с хорошим старым». модные методы ADO.NET. & quot;

Похожие вопросы