16

私はNxNテーブルを持っています、想像してください:

User(id, ...) <- UserAddresses(id, userId, addressId, enabled, ...) -> Addresses(id, ...)

UserAddresses には、ユーザーおよびアドレスへの FK が含まれています。私の知る限り、Entity Framework ユーザーによって作成されたエンティティには、UserAddresses へのコレクションが含まれています。Address には UserAddresses へのコレクションが含まれており、特定の UserAddress には User と 1 つの Address への 1 つの参照が含まれています。

今度はlinqで次のクエリを作成したいと思います。特定のユーザー ID について、有効フラグが true に設定された userAddresses のみを取得します。特定のユーザー ID の場合、userAddresses には複数のエントリを含めることができますが、この特定のユーザーには 1 つしか設定されません。

私ができるクエリは次のとおりです。

context.User.Include( x => x.UserAddresses )
            .Include( x => x.UserAddresses.Select(y => y.Address) )
            .Single( x => x.id == USER_ID )

しかし、私が本当に望んでいるのは、そのユーザーのすべての UserAddresses をロードすることではありません...有効にされ、TRUE に設定されているものだけです!

誰かがこのクエリを実行するのを手伝ってくれますか?

4

2 に答える 2

16

EF では、関連付けプロパティを部分的に読み込む方法はありません。匿名型を選択して、必要なものだけを取得してみてください。

var result = context.User
   .Where(u => u.Id == userId)
   .Select(u => new {
       Addresses = u.UserAddresses.Select(ua => ua.Address)
            .Where(a => a.Enabled),
       User = u // if you need this as well 
   })
   .Single();

これはresult.User.UserAddressesをロードしませんが、result.Addressesにはまさにあなたが望むものがあります。

本当にすべてを User クラスの一部として返したい場合は、result.User をデタッチしてから、result.User.UserAddresses を更新して、result.Addresses を指すようにする必要があります。

于 2013-10-15T16:45:16.043 に答える
1

別の代替オプションは、Load()代わりに使用していますInclude()

var foundUser = context.User.Single(x => x.Id == USER_ID);

context.Entry(foundUser).Collection(u =>
u.UserAddresses).Query().Where(userAddress =>
userAddress.Enabled).Load();

Load()一部のシナリオでは、メソッドが EF によって無視される可能性があることに注意してください。

  1. 遅延読み込み機能と共に EF を使用している場合、オブジェクトをフェッチすると、クラスで Virtual としてマークされているすべての関連コレクションが取得されます。したがって、User クラスのプロパティからキーワードをcontext.User.Single( x => x.id == USER_ID );削除してコレクションの遅延読み込みをオフにしない限り、User に関連付けられたすべての UserAddresses を取得します。Virtual

  2. プログラムで UserAddresses コレクションを追加/削除していて、context.SaveChanges(); を呼び出した場合。コンテキストを破棄せずに、次に User オブジェクトをロードするときに、UserAddresses コレクションは DB からではなく EF コンテキスト キャッシュからロードされます (最新の変更)。この場合、コンテキストからユーザーを取得する前に、コンテキストを破棄して新しいコンテキストをインスタンス化する必要があります。たとえば、UserAddresses コレクションに 5 つのアイテムを持つ User があり、アイテムの 1 つを無効にして ( item.Enabled = false)、コンテキストを破棄せずに呼び出しcontext.SaveChanges()た場合、次に同じコンテキストから User オブジェクトを取得したときに、既に 5 つのアイテムが含まれています。コンテキストキャッシュからのコレクションであり、メソッドを無視しますLoad()

PS:

以下のすべての条件が適用される場合、遅延読み込み機能がオンになります。

  1. context.Configuration.LazyLoadingEnabled = true;
  2. context.Configuration.ProxyCreationEnabled = true;
  3. UserAddresses は User クラスで Virtual として定義されています。
于 2014-08-08T00:16:36.900 に答える