web-dev-qa-db-ja.com

積極的な読み込みのためにLINQ式の構文はInclude()でどのように機能しますか

以下のクエリがありますが、Include()を実行して負荷プロパティを積極的に取得したいです。アクションには、ユーザー(Action.User)というナビゲーションプロパティがあります

1)私の基本的なクエリ:

from a in Actions
join u in Users on a.UserId equals u.UserId
select a

2)最初の試行:

from a in Actions.Include("User")
join u in Users on a.UserId equals u.UserId
select a

ただし、Action.Userはnotが設定されています。

3)クエリ以外のアクションで、ナビゲーションプロパティに「ユーザー」を積極的にロードしてみます。

(from a in Actions
join u in Users on a.UserId equals u.UserId    
select a).Include("User")

インクルードをしようとしているLINQPadでエラーが発生します:

「System.Linq.IQueryable」には「Include」の定義が含まれておらず、タイプ「System.Linq.IQueryable」の最初の引数を受け入れる拡張メソッド「Include」が見つかりませんでした(F4キーを押してusingディレクティブまたはアセンブリ参照を追加します) )

これは、LINQがInclude()をサポートしていないためだと思います。

だから私はVSで試しました。クエリ2は実行されますが、未入力のユーザープロパティを返します。クエリ3拡張メソッドは存在しないように見えますが、クエリなしのAction自体には存在します。

31
jaffa

とにかく提案に感謝します。解決策はこれを行うことです(私の質問の2回目の試み):

var qry = (from a in Actions
join u in Users on a.UserId equals u.UserId    
select a).Include("User")

クエリの後にインテリセンスがインクルードを表示しなかった理由は、以下を使用する必要があるためです。

using System.Data.Entity;

これを行うとすべてがうまくいきました。

59
jaffa

必要なのが、関連するActionエンティティがAction.UserId外部キープロパティ を介して実際に存在するすべてのUserエンティティを返すクエリである場合、これは実行されますそれ:

var results = context.Actions
    .Include("User")
    .Where(action =>
        context.Users.Any(user =>
            user.UserId == action.UserId));

ただし、ナビゲーションプロパティ もあるため、フィルタリングを行うために外部キープロパティを使用する必要はありません。そのため、次の例のように、代わりにAction.Userナビゲーションプロパティでフィルタリングすることにより、クエリを簡素化できます。

var results = context.Actions
    .Include("User")
    .Where(action => action.User != null);

モデルでAction.Userプロパティがnullになることはない(つまり、Action.UserId外部キーはデータベースでnullにできない)と指定されており、実際にすべてのActionエンティティが関連付けられている場合Users、クエリはさらにシンプルになります

var results = context.Actions.Include("User");
16

より良い、リファクタリングしやすいコード(EF6)

using System.Data.Entity;
[...]
var x = (from cart in context.ShoppingCarts
         where table.id == 123
         select cart).Include(t => t.CartItems);

または

var x = from cart in context.ShoppingCarts.Include(nameof(ShoppingCart.CartItems))
        where table.id == 123
        select cart;

2017年3月31日更新

どちらの方法でも、ラムダ構文にincludeを使用できます。

var x = from cart in context.ShoppingCarts.Include(p => p.ShoppingCart.CartItems))
        where table.id == 123
        select cart;
14
K0D4

投稿された質問に記載されている基本的なクエリを実行すると、次のような匿名型を返さない限り、ユーザープロパティを表示できません。

from a in Actions
join u in Users on a.UserId equals u.UserId
select new
{
   actionUserId = a.UserId
   .
   .
   .
   userProperty1 = u.UserId
};

ただし、ObjectContextでIncludeメソッドを使用するには、次を使用できます。

次の行を使用して、LazyLoadingがオフになっていることを確認します。

entities.ContextOptions.LazyLoadingEnabled = false;

次に進む

var bar = entities.Actions.Include("User");
var foo = (from a in bar
           select a);
2
Ryan

これにはLoadWithオプションを使用します

var dataOptions = new System.Data.Linq.DataLoadOptions();
dataOptions.LoadWith<Action>(ac => as.User);
ctx.LoadOptions = dataOptions;

それでおしまい。 ctxはDataContextです。これは私のために働く:-)

0
Mariusz