Обновления
Это сложно для 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.2018DbQuery
был заменен типами сущностей без ключа, использующимиDbSet
в EF Core 3. 13.11.2019