Использование SqlQuery для получения IQueryable

Есть ли что-то, что может вернуть IQueryable для динамического SQL-запроса в Entity Framework 6?

Это то, что я сейчас использую, но он тянет все записи (как и ожидалось).

DbContext.Database.SqlQuery<T>("SELECT * FROM dbo.SomeDynamicView")

Проблема в том, что SqlQuery возвращает DbRawSqlQuery, который равен IEnumerable.

dbo.SomeDynamicView - это представление базы данных, созданное во время выполнения.

Ответ 1

Нет, вы не можете получить IQueryable из SqlQuery * потому что то, что IQueryable выполняет, строит строку SQL динамически на основе того, что выбирает и где фильтрует вас введите. Поскольку в SqlQuery вы предоставляете строку, Entity Framework не может сгенерировать эту динамическую строку.

Ваши параметры либо динамически строят строку, в которой ваш я должен перейти к SqlQuery, и использовать ее как IEnumerable вместо IQueryable или использовать DbSet в вашем DbContext и делать больше "нормальный" способ предоставления объектной структуры для вас.


* Вы технически можете, вызвав AsQueryable() в результате, но это просто IEnumerable, притворяющийся IQueryable, он не дает вам каких-либо преимуществ использования "Реального" IQueryable, например, только для получения необходимых строк с сервера.

Ответ 2

Я знаю, что этот вопрос касается EF6, но в случае, если кто-то еще наткнется на этот вопрос, но интересуется EFCore, на самом деле это возможно.

Самый простой пример:

var user = new SqlParameter("user", "johndoe");

var blogs = context.Blogs
    .FromSqlRaw("EXECUTE dbo.GetMostPopularBlogsForUser @user", user)
    .ToList();

Параметры:

var user = new SqlParameter("user", "johndoe");

var blogs = context.Blogs
    .FromSqlRaw("EXECUTE dbo.GetMostPopularBlogs @[email protected]", user)
    .ToList();

Более сложный пример (это более конкретно то, о чем спрашивает этот вопрос):

var searchTerm = ".NET";

var blogs = context.Blogs
    .FromSqlInterpolated($"SELECT * FROM dbo.SearchBlogs({searchTerm})")
    .Where(b => b.Rating > 3)
    .OrderByDescending(b => b.Rating)
    .ToList();

Результирующий запрос для более сложного примера:

SELECT [b].[Id], [b].[Name], [b].[Rating]
        FROM (
            SELECT * FROM dbo.SearchBlogs(@p0)
        ) AS b
        WHERE b."Rating" > 3
        ORDER BY b."Rating" DESC

Несколько замечаний об этом методе:

  • Вы фактически должны сделать SELECT *, чтобы убедиться, что все столбцы возвращены из таблицы.
  • Объединения для извлечения дополнительных данных не работают, но Include работает в обычных запросах SQL (не обязательно хранимых вызовах процедур/функций).
  • Часто ваш сырой Sql будет помещен в подзапрос. Поэтому убедитесь, что он действителен для таких вещей (то есть точки с запятой, порядок байтов, подсказки и т.д. Могут вызвать проблемы).

Ответ 3

Да Вы можете сделать следующее:

DbContext.Database.SqlQuery("SELECT * FROM dbo.SomeDynamicView").AsQueryable<T>()