0

Entity Framework で関係をモデル化する方法について混乱しています。

ClassAオプションで を指したいClassB。これは、オプションの 1 対 1 の関係のように思えます。

ClassBまた、それを指す ClassA を常に指しておきたいと思います。ClassBまた、複数の が同じ を参照できるようにしたいと考えていClassAます。1 対多の関係のように聞こえます。

これは 1 つの関係としてモデル化するのが最適ですか、それとも実際には 2 つの完全に別個の関係ですか?

2 つの関係の場合、参照に使用される ClassB に表示される単一のプロパティ「ClassAKey」を共有できますClassAか?

私の問題では、OMをどうしたいかは頭の中で明らかです。

ClassA
{
    [Key]
    int Key { get; set; }
    ClassB Maybe { get; set; }
    int MaybeKey { get; set; }
}

ClassB
{
    [Key]
    int Key { get; set; }
    ClassA Always { get; set; }
    int AlwaysKey { get; set; }
}

また、DB でどのように表示されるかは、頭の中で明確です。それぞれが相互に参照できるように、1 つの列と 1つのClassAKey列だけが存在し、これらの列の外部キー関係が必要です。ClassBClassBKeyClassA

しかし... EFでこれをモデル化する方法が何であるかは明確ではありません。実際、私は何か間違ったことをしているに違いないようです!上記のコードから始めると、エラーが発生します。

Unable to determine the principal end of an association between the types 'ClassA' and 'ClassB'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.

このように設定しようとすると、

modelBuilder.Entity<ClassA>()
            .HasOptional(a => a.Maybe)
            .WithRequired(b => b.Always);

何らかの理由で、ClassB が間違った外部キー プロパティを持つ場所で生成された間違ったデザイナー コードのように見えるものを取得します。

.ForeignKey("dbo.ClassAs", t => t.Key)

t.AlwaysKey のはずですよね?どうしたの!?

4

2 に答える 2

1

私の理解が正しければ、 と の間に One:Many オプションの関係を作成しようとしていClassAますClassB。またClassB、関連付けられた が常に必要なように思えます。これにより、プリンシパルと従属ClassAが作成されます。ClassAClassB

ClassB最初に、 (の)のナビゲーション プロパティを変更する必要がありますClassA。多くの関係が必要なため、オブジェクトを格納するための何らかのコレクションが必要になりClassBます。

これは、参照している単一のオブジェクトが存在しないため、 MaybeKeyinを削除することを意味し、代わりにコレクション (例: ) が作成されます。また、参照する対応するテーブルの列も必要ありません(1 対多の関係であるため、1 つの列では機能しません)。が関連する を参照する、テーブル内の外部キー列のみが必要です。ClassAICollection<ClassB>ClassAClassBClassBClassAClassB

コードは次のようになります。

public class ClassA
{
    [Key]
    public int Key { get; set; } // ClassA Key

    public virtual ICollection<ClassB> MyClassBs { get; set; } // Your optional dependants.
}

public class ClassB
{  
    [Key]
    public int Key { get; set; } // ClassB key

    public int AKey { get; set; } // Your foreign key.
    public virtual ClassA myClassA { get; set; } // Your principal.
}

ナビゲーション プロパティはマークされvirtualているため、Entity Framework はそれらをオーバーライドし、必要に応じて遅延読み込み機能を提供できます。

マッピングを作成するには、これらの行に沿って何かを行います (目標を誤解していた場合は、変更が必要になる場合があります)。

modelBuilder.Entity<ClassA>()
            .HasMany(b => b.MyClassBs)     // Many ClassBs
            .WithRequired(a => a.myClassA) // Each ClassB requires a ClassA
            .HasForeignKey(b => b.AKey);   // Use Akey as a foreign key

これを表現するには、いくつかの方法があります (たとえば、横から表現できますClassB)。

エンティティ フレームワークには利用できるデフォルトの規則IDがいくつかあるため、主キーや外部キーのような名前など、もう少し慣習的な命名に固執する価値があるかもしれません。また、他の人がコードを読むのが少し簡単になります (同様の規則に遭遇する傾向があるため)。ClassAID

編集:「特別な」関係を含むように更新されました。

あなたClassAには、次のフィールドを含めることができます(元の例ではすでに別の名前で持っていました):

public int SpecialBID { get; set; }
public virtual ClassB SpecialB { get; set; }

次のマッピングを追加します。

modelBuilder.Entity<ClassA>()
            .HasOptional(x => x.SpecialB)
            .WithMany()
            .HasForeignKey(x => x.SpecialBID);

あなたのがあなたのコレクションSpecialBに含まれているという保証はありませんが.MyClassBs

リレーションシップの反対側 (classB オブジェクト内) でナビゲーション プロパティを必要としないリレーションシップ マッピングを使用して、MyClassBs コレクションを ClassA から完全に削除することもできます。

    modelBuilder.Entity<ClassB>()
        .HasRequired(x => x.myClassA)
        .WithMany()
        .HasForeignKey(x => x.AKey);
于 2013-07-17T13:08:19.193 に答える