Я вижу, что расширение SqlQuery было изменено на FromSql
Но новый метод FromSql
более рестриктивен, чем SqlQuery
.Документация этого метода объясняет, что существуют некоторые ограничения, такие как:
Запросы SQL могут использоваться только для возврата типов сущностей, которые являются частью вашей модели..В нашем бэклоге есть усовершенствование , позволяющее возвращать специальные типы из необработанных запросов SQL .
Запрос SQL должен возвращать данные для всех свойств объекта илитип запроса .
[...]
Итак, в вашем случае используется следующий SQL-запрос:
SELECT a.title FROM a JOIN b ON b.Id = a.aId WHERE b.Status = 10
Как сказано в документации, вы можете использовать FromSql
только с сущностью или типом запроса .Ваш запрос SQL не возвращает все данные вашей сущности, определенные в вашей модели, но возвращает только один столбец вашей сущности.Между прочим, в EF Core 2.1 появилась новая функция, которая находится в версии-кандидате с 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;
Не хотите использовать DbQuery<T>
Если выне хотите использовать DbQuery<T>
и не хотите определять класс, который содержит только одно свойство, тогда вы можете использовать ExecuteSqlCommandAsync
, как @ vivek nuna в своем ответе (его ответ частично правильный).Но вы должны знать, что возвращаемое значение этого метода - это количество строк, затронутых вашим запросом.Также вы должны поместить свой заголовок в качестве выходного параметра, чтобы сделать ваш запрос хранимой процедурой.Используйте ExecuteSqlCommandAsync
или ExecuteSqlCommand
и после этого прочитайте выходной параметр, который вы передали при вызове метода.
Более простой способ без создания хранимой процедуры, поэтому без использования ExecuteSqlCommandAsync
или ExecuteSqlCommand
, заключается в следующемcode:
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
.