0

コードファーストのシナリオから Entity Framework (6) を独学で学び始めたところです。私の問題は、特定のエンティティが他のエンティティ間で共有される可能性があることを EF に正しく指示する方法がわからないことです。

これは、3 レベルのツリー構造を持つ非常に単純なシナリオです。クラスAオブジェクトは、クラスBオブジェクトを所有または参照するクラス オブジェクトを所有しCます。

public class A
{
    [Key]
    public string Id { get; set; }

    public ICollection<B> Bees { get; set; }

    public override string ToString() { return Id; }
}

public class B
{
    [Key]
    public string Id { get; set; }

    public ICollection<C> Cees { get; set; }

    public override string ToString() { return Id; }
}

public class C
{
    [Key]
    public string Id { get; set; }

    public override string ToString() { return Id; }
}

ここで、1 つのオブジェクトが 5 つのオブジェクトをA所有し、5つのオブジェクトのコレクションを共有するシナリオを作成します。私が使用したDbContextは次のとおりです。BC

public class Context : DbContext
{
    public DbSet<A> As { get; set; }

    public DbSet<C> Cs { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        // SHOULD I INSTRUCT EF HOW TO HANDLE THIS HERE?
        base.OnModelCreating(modelBuilder);
    }

    public Context(string nameOrConnectionString)
        : base(nameOrConnectionString)
    {
    }
}

このシナリオを設定するための簡単なコードを次に示します。

internal class Program
{
    private static void Main(string[] args)
    {
        var context = new Context(@"Data Source=(localdb)\v11.0; Initial Catalog=TestEF6.Collections; Integrated Security=true");
        var sharedCees = createCees("A1.B1", 5, context);
        context.As.Add(new A { Id = "A1", Bees = createBees("A1", 5, sharedCees) });
        context.SaveChanges();
    }

    private static ICollection<B> createBees(string aId, int count, ICollection<C> cees = null)
    {
        var list = new List<B>();
        for (var i = 0; i < count; i++)
        {
            var id = aId + ".B" + (i + 1);
            list.Add(new B { Id = id, Cees = cees ?? createCees(id, count) });
        }
        return list;
    }

    private static ICollection<C> createCees(string bId, int count, Context saveInContext = null)
    {
        var list = new List<C>();
        for (var i = 0; i < count; i++)
        {
            var id = bId + ".C" + (i+1);
            var c = new C {Id = id};
            list.Add(c);
            if (saveInContext != null)
                saveInContext.Cs.Add(c);
        }
        if (saveInContext != null)
            saveInContext.SaveChanges();
        return list;
    }
}

EF がデータベース ('TestEF6.SharedEntities') を作成するとき、 1 対多の関係であるA -> BだけでなくB -> C、子エンティティがコンポーネントであり、そのマスター エンティティによって完全に所有および制御されていると想定します。

Cでは、 のインスタンスが のインスタンスで共有できることを EF に「認識」させるにはどうすればよいBでしょうか。

正直なところ、私は EF を手早く始めたいと思っています。私はウェブを耕してこれを理解できることを認識していますが、誰かが私を正しい方向に向けることができれば、とても感謝しています.

乾杯

4

1 に答える 1

0

CGert は、クラスにコレクション プロパティを追加することを提案して、私を軌道に乗せました。実際、EF/CF が と の間の多対多の関係を自動的に認識するには、これで十分BですC。しかし、コード ファーストの要点は、クラスのドメイン モデルを設計し、永続性情報でそれらを行き詰まらせずに EF に永続化させることです。

Keyプロパティに注釈を付けることに問題はありませんRequired。この種の情報は、ドメイン モデルでは実際に意味があります。それらはドメイン コードで使用できますが、そうでなくても、コードを明確にします。しかし、EF の auto-magic へのヒントとして機能する以外に機能しないプロパティを追加することは、非常に洗練されたソリューションとは思えませんでした。

そこで、流暢な API をさらに試してみたところ、 のパラメーターなしのオーバーロードを見逃していたことに気付きました.WithMany()。私は、他のタイプの多対多関係を指定できるようにする一般的な形式を探していました。私の心の中では、次のように書きますmodelBuilder.Entity<B>.HasMany(b => b.Cees).WithMany<B>()。結局のところ、このシナリオの型は最初の部分で既に指定されているため、 のパラメーターなしのオーバーロードはWithMany()まさにこの目的を果たします。CHasMany()

Bつまり、要約すると、EF はクラスとの間の多対多の関係を認識し、タイプ項目の追加のジェネリック コレクションをクラスCに「散らかす」必要はありません。したがって、これは、ドメイン クラスにまったく触れることなく、2 つのクラス間の多対多の関係を記述する方法です。CB

public class Context : DbContext
{
    public DbSet<A> As { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<B>().HasMany(b => b.Cees).WithMany(); // <-- THE SOLUTION
        base.OnModelCreating(modelBuilder);
    }

    public Context(string nameOrConnectionString)
        : base(nameOrConnectionString)
    {
    }
}

これは EF に慣れている人にとっては非常に基本的なことだと思いますが、先に進んでこれを回答としてマークし、他の人が将来この情報を探す時間を節約できるようにします。

ありがとう

于 2014-02-06T11:55:10.210 に答える