Nano Hash - криптовалюты, майнинг, программирование

Как выполнить SqlQuery с Entity Framework Core 2.1?

В Entity Framework 6 я могу выполнить необработанный SQL-запрос к базе данных, используя следующую команду:

IEnumerable<string> Contact.Database.SqlQuery<string>("SELECT a.title FROM a JOIN b ON b.Id = a.aId WHERE b.Status = 10");

В новом проекте я пытаюсь использовать Entity Framework Core 2.1. Мне нужно выполнить необработанный SQL-запрос. Во время поиска я заметил, что расширение SqlQuery было изменено на FromSql. Однако FromSql существует только на DbSet<>, а не на DbContext.Database.

Как я могу запустить FromSql вне DbSet<>? Метод FromSql не существует для объекта базы данных DbContext.Database.FromSql<>.



Ответы:


1

Обновления

Это сложно для EF Core 2.1, но если вы используете EF Core 3.0 или более поздние версии, обратитесь к этому полный ответ.


Я вижу, что расширение SqlQuery было изменено на FromSql

Но новый FromSql метод более строг, чем SqlQuery. В документации этого метода объясняется, что он существует такие ограничения, как:

Запросы SQL можно использовать только для возврата типов сущностей, которые являются частью вашей модели. В нашем бэклоге есть улучшение, позволяющее возвращать специальные типы из необработанных запросов SQL .
Запрос SQL должен возвращать данные для всех свойств объекта или типа запроса.

[...]
Обновление: недавнее обсуждение GitHub dotnet / efcore Поддержка сырых SQL-запросов без определения типа объекта для результата # 10753

Итак, в вашем случае SQL-запрос, который вы используете, выглядит следующим образом:

SELECT a.title FROM a JOIN b ON b.Id = a.aId WHERE b.Status = 10

Как сказано в документации, вы можете использовать FromSql только с типом объекта или запроса. Ваш SQL-запрос не возвращает все данные вашей сущности, определенной в вашей модели, но возвращает только один столбец вашей сущности. Кстати, новая функция представлена ​​в EF Core 2.1, который находится в Release Candidate с 7 мая 2018 года. Microsoft сообщает:

EF Core 2.1 RC1 - это «действующий» выпуск, что означает, что после проверки правильности работы вашего приложения с RC1 вы сможете использовать его в производственной среде и получить поддержку от Microsoft, но вам все равно следует выполнить обновление до окончательной стабильной версии, как только она станет доступна. .

## Использование FromSql для типа запроса ##

Что такое тип запроса:

Модель EF Core теперь может включать типы запросов. В отличие от типов сущностей, типы запросов не имеют определенных ключей и не могут быть вставлены, удалены или обновлены (т.е. они доступны только для чтения), но они могут быть возвращены непосредственно запросами. Вот некоторые из сценариев использования типов запросов: сопоставление с представлениями без первичных ключей, сопоставление с таблицами без первичных ключей, сопоставление с запросами, определенными в модели, использование в качестве возвращаемого типа для запросов FromSql ()

Если вы хотите использовать функцию типа запроса с вашим текстом SQL, вы сначала определяете класс, назовите его MySuperClass:

public class MySuperClass
{
    public string Title { get; set; }
}

Затем в вашем классе DbContext определено свойство типа DbQuery<MySuperClass>, как показано ниже:

public DbQuery<MySuperClass> MySuperQuery { get; set; }

Наконец, вы можете использовать FromSql, как показано ниже:

var result = context.MySuperQuery.FromSql("SELECT a.title FROM a JOIN b ON b.Id = a.aId WHERE b.Status = 10").ToList().First();
var title = result.Title;

## Не хочу использовать _12 _ ## Если вы не хотите использовать DbQuery<T> и не хотите определять класс, содержащий только одно свойство, вы можете использовать ExecuteSqlCommandAsync, например @ vivek nuna сделал в своем ответе (его ответ частично правильный). Но вы должны знать, что возвращаемое этим методом значение - это количество строк, затронутых вашим запросом. Также вы должны указать свой заголовок в качестве выходного параметра, чтобы сделать ваш запрос хранимой процедурой. Используйте ExecuteSqlCommandAsync или ExecuteSqlCommand и после этого прочтите выходной параметр, который вы передали при вызове метода.

Более простой способ без создания хранимой процедуры, поэтому без использования ExecuteSqlCommandAsync или ExecuteSqlCommand, заключается в следующем коде:

using (var context = new MyDbContext())
{
    var conn = context.Database.GetDbConnection();
    await conn.OpenAsync();
    var command = conn.CreateCommand();
    const string query = "SELECT a.title FROM a JOIN b ON b.Id = a.aId WHERE b.Status = 10";
    command.CommandText = query;
    var reader = await command.ExecuteReaderAsync();
    while (await reader.ReadAsync())
    {
        var title = reader.GetString(0);
        // Do whatever you want with title 
    }
}  

Вы можете сделать эту логику вспомогательным методом, который будет получать ваш SQL-запрос и возвращать желаемые данные. Но я рекомендую вам использовать Dapper.Net, который содержит множество вспомогательных методов, которые помогут легко справиться с RAW SQL, как мы делали выше, а также совместное использование smae-соединения с DbContext.

18.05.2018
  • Где вы устанавливаете значение свойства public DbQuery<MySuperClass> MySuperQuery { get; set; }? Я пытаюсь понять, где взять экземпляр DbQuery, потому что класс абстрактный. Надо ли делать индивидуальный? В этом нет ничего, что можно было бы переопределить, поэтому я не понимаю. 23.10.2018
  • Вам нужен класс, который EF может создать при материализации. Так что абстрактный класс работать не будет. Вам нужен собственный @ rory.ap 24.10.2018
  • как передать параметры? 03.08.2019
  • Обратите внимание, что DbQuery был заменен типами сущностей без ключа, использующими DbSet в EF Core 3. 13.11.2019
  • Зачем добавлять этот ответ вместо того, чтобы просто пометить вопрос как дубликат Raw SQL Query без DbSet - Entity Framework Core? 09.03.2021

  • 2

    Вы можете использовать метод ExecuteSqlCommandAsync, который определен в классе RelationalDatabaseFacadeExtensions сборки Microsoft.EntityFrameworkCore.Relational следующим образом.

    _databaseContext.Database.ExecuteSqlCommandAsync(<Your parameters>)
    
    18.05.2018
  • Это только выполняет SQL, он не возвращает набор результатов 23.03.2020
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..