Можно ли запустить собственный sql с Entity framework?


Я пытаюсь найти поле XML в таблице, это не поддерживается с помощью EF.

без использования чистого Ado.net можно ли иметь собственную поддержку SQL с EF?

7 65

7 ответов:

для .NET Framework версии 4 и выше: используйте ObjectContext.ExecuteStoreCommand() если ваш запрос не возвращает никаких результатов, и использовать ObjectContext.ExecuteStoreQuery если ваш запрос возвращает результаты.

для предыдущих версий .NET Framework, вот пример, иллюстрирующий, что делать. Замените ExecuteNonQuery () по мере необходимости, если ваш запрос возвращает результаты.

static void ExecuteSql(ObjectContext c, string sql)
{
    var entityConnection = (System.Data.EntityClient.EntityConnection)c.Connection;
    DbConnection conn = entityConnection.StoreConnection;
    ConnectionState initialState = conn.State;
    try
    {
        if (initialState != ConnectionState.Open)
            conn.Open();  // open connection if not already open
        using (DbCommand cmd = conn.CreateCommand())
        {
            cmd.CommandText = sql;
            cmd.ExecuteNonQuery();
        }
    }
    finally
    {
        if (initialState != ConnectionState.Open)
            conn.Close(); // only close connection if not initially open
    }
}

используя Entity Framework 5.0 можно использовать ExecuteSqlCommand выполнить многоканальный/многокомандный чисто SQL заявления. Таким образом, вам не нужно будет предоставлять какой-либо резервный объект для хранения возвращаемого значения, так как метод возвращает int (результат, возвращенный базой данных после выполнения команды).

пример:

context.Database.ExecuteSqlCommand(@
"-- Script Date: 10/1/2012 3:34 PM  - Generated by ExportSqlCe version 3.5.2.18
SET IDENTITY_INSERT [Students] ON;

INSERT INTO [Students] ([StudentId],[FirstName],[LastName],[BirthDate],[Address],[Neighborhood],[City],[State],[Phone],[MobilePhone],[Email],[Enrollment],[Gender],[Status]) VALUES (12,N'First Name',N'SecondName',{ts '1988-03-02 00:00:00.000'},N'RUA 19 A, 60',N'MORADA DO VALE',N'BARRA DO PIRAÍ',N'Rio de Janeiro',N'3346-7125',NULL,NULL,{ts '2011-06-04 21:25:26.000'},2,1);

INSERT INTO [Students] ([StudentId],[FirstName],[LastName],[BirthDate],[Address],[Neighborhood],[City],[State],[Phone],[MobilePhone],[Email],[Enrollment],[Gender],[Status]) VALUES (13,N'FirstName',N'LastName',{ts '1976-04-12 00:00:00.000'},N'RUA 201, 2231',N'RECANTO FELIZ',N'BARRA DO PIRAÍ',N'Rio de Janeiro',N'3341-6892',NULL,NULL,{ts '2011-06-04 21:38:38.000'},2,1);
");

для получения дополнительной информации об этом, посмотрите здесь:Entity Framework Code First: выполнение SQL-файлов при создании базы данных

на 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 + "' )";


    return context.Database.SqlQuery<PanelSerialList>(panelSerialByLocationAndStockQuery).ToList();


}

начиная с .NET 4 Вы можете использовать ExecuteStoreQuery способ:

var list = myDBEntities.ExecuteStoreQuery<MyClass>(MyClass.sql);

где myDBEntities наследуется от ObjectContext.

class MyClass
{
    /* You can change query to more complicated, e.g. with joins */
    public const string sql = @"select [MyTable].[MyField] from [MyTable]";
    public string MyField { get; set; }
}

обратите внимание, что MyTable-это реальное имя таблицы, а не класс EF.

сохранить его простым

using (var context = new MyDBEntities())
{
    var m = context.ExecuteStoreQuery<MyDataObject>("Select * from Person", string.Empty);
    //Do anything you wonna do with 
    MessageBox.Show(m.Count().ToString());
}
public class RaptorRepository<T>
    where T : class
{
    public RaptorRepository()
        : this(new RaptorCoreEntities())
    {
    }

    public RaptorRepository(ObjectContext repositoryContext)
    {
        _repositoryContext = repositoryContext ?? new RaptorCoreEntities();
        _objectSet = repositoryContext.CreateObjectSet<T>();
    }

    private ObjectContext _repositoryContext;
    private ObjectSet<T> _objectSet;
    public ObjectSet<T> ObjectSet
    {
        get
        {
            return _objectSet;
        }
    }


    public void DeleteAll()
    {
        _repositoryContext
            .ExecuteStoreCommand("DELETE " + _objectSet.EntitySet.ElementType.Name);
    }
}

Так что же мы скажем обо всем этом в 2017 году? 80k консультации предполагает, что запуск SQL-запроса в EF-это то, что многие люди хотят сделать. Но почему? Для какой пользы?

Джастин, гуру с 20-кратной моей репутацией, в принятом ответе дает нам статический метод, который выглядит строка за строкой как эквивалентный код ADO. Обязательно скопируйте его хорошо, потому что есть несколько тонкостей, чтобы не ошибиться. И вы обязаны объединить свой запрос с параметрами времени выполнения, так как там нет никаких условий для надлежащих параметров. Таким образом, все пользователи этого метода будут строить свой SQL со строковыми методами (хрупкий, непроверяемый, SQL-инъекция), и ни один из них не будет модульным тестированием.

другие ответы имеют те же ошибки, только moreso. SQL похоронен в двойных кавычках. Возможности SQL-инъекции щедро разбросаны вокруг. Уважаемые коллеги, это абсолютно дикое поведение. Если бы это был сгенерированный C#, была бы война пламени. Мы даже не принимаем генерация HTML таким образом, но как-то его ОК для SQL. Я знаю, что параметры запроса не были предметом вопроса, но мы копируем и повторно используем то, что видим, и ответы здесь являются как моделями, так и заветами того, что делают люди.

разве эф расплавил наши мозги? EF не хочет, чтобы вы использовали SQL, поэтому зачем использовать EF для SQL.

желание использовать SQL для общения с реляционной БД-это здоровый, нормальный импульс у взрослых. QueryFirst показывает, как это может быть сделано разумно, ваш sql В.sql-файл, проверенный при вводе, с помощью intellisense для таблиц и столбцов. Оболочка C# генерируется инструментом, поэтому ваши запросы становятся доступными в коде, с intellisense для ваших входных данных и результатов. Конец в конец сильного набора текста, никогда не беспокоясь о типе. Нет необходимости запоминать имя столбца или его индекс. И есть множество других преимуществ... Искушение сцепить - это удалены. Возможность неправильного подключения тоже. Все ваши запросы и код, который обращается к ним, постоянно тестируются на интеграцию с вашей базой данных dev. Изменения схемы в вашей БД всплывают как ошибки компиляции в вашем приложении. Мы даже создаем метод самотестирования в оболочке, так что вы можете тест новые версии вашего приложения против существующих производственных баз данных, а не ждать звонка телефона. Кого еще нужно убеждать?

отказ от ответственности: я написал QueryFirst : -)