3

以前は、多対多の関係や POCO のリレーショナル Id などのすべてのヘルパー テーブルを自分で生成していましUsergroupUsersたが、今では EF にそれらを処理してもらいたいと考えています。結局のところ、それはそれほど良い考えではないと思います。

問題

UsergroupDynamicField特定のユーザーのすべてを取得しようとするとN+1、ユーザーが属するすべてのユーザーグループに対してクエリが生成されます。

ここでは、の代わりにUsergroupsが になると単純に述べるだけで、この問題を克服しました。EFはそれをマップしないため、今はそれを行うことができません。IQUeriableIEnumerableICollection

コード

public class User
{
    ...
    public virtual ICollection<Usergroup> Usergroups { get; set; }
    public IEnumerable<UserField> Fields
    {
        get
        {
            var fields = this.Usergroups.SelectMany(x => x.UsergroupDynamicFields); // N + 1 for every Usergroup

            foreach (var field in fields)
            {
                yield return new UserField
                {
                    Name = field.Name
                };
            }
        }
    }
}

データベース

DB DB2

4

2 に答える 2

1

ここでは、Usergroups が IEnumerable ではなく IQUeriable になると単純に述べるだけで、この問題を克服しました。EFはそれをマップしないため、今はそれを行うことができません.ICollectionでなければなりません.

しかし、最終的に実装するクラスICollectionEntityCollection<T>. このコレクションには、使用できるCreateSourceQuery()機能があります。

var usergroupsQuery = ((EntityCollection<UserGroup>)this.Usergroups).CreateSourceQuery();
var fields = usergroupsQuery.SelectMany(x => x.UsergroupDynamicFields);

更新: コメントで指摘されているように、変更の追跡が可能で有効になっている場合 (封印されていないクラス、およびすべての関連するプロパティ)ICollection<T>を使用してのみ実装されます。別の方法でクエリを作成できます。EntityCollection<T>virtual

var usergroupsQuery = db.Entry(this).Collection(u => u.Usergroups).Query();
var fields = usergroupsQuery.SelectMany(x => x.UsergroupDynamicFields);

dbこれには何らかの方法でアクセスできる必要があることに注意してください。

于 2013-07-25T14:24:27.880 に答える