web-dev-qa-db-ja.com

SqlQueryを使用してIQueryableを取得する

Entity Framework6の動的SQLクエリに対してIQueryableを返すことができるものはありますか?

これは私が現在使用しているものですが、すべてのレコードをプルしています(予想どおり)。

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

問題は、SqlQueryDbRawSqlQuery を返すことです。これはIEnumerableです。

dbo.SomeDynamicViewは、実行時に作成されるデータベースビューです。

17
Oxon

いいえ、IQueryableからSqlQueryを取得することはできません*、これは、IQueryableが実行しているのは、入力した選択と場所に基づいてSQL文字列を動的に構築するためです。SqlQueryでは文字列を提供しているため、EntityFrameworkはその動的な文字列を生成できません。ストリング。

オプションは、自分で文字列を動的に作成してSqlQueryに渡し、それをIEnumerableではなくIQueryableとして使用するか、DbSetを使用することです。 DbContextを実行し、エンティティフレームワークにクエリを構築させるためのより「通常の」方法を実行します。


*技術的には、結果に対して AsQueryable() を呼び出すことで可能ですが、これはIQueryableのふりをしているIEnumerableであり、「実際の」IQueryableを使用するメリットはありません。サーバーから必要な行を取得します。

19

私はこの質問が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 @filterByUser=@user", 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はサブクエリに入れられます。したがって、そのような場合に有効であることを確認してください(つまり、セミコロン、順序付け、ヒントなどが問題を引き起こす可能性があります)。
0
Jaxidian