1

MemberAuthenticationToken、およびの3 つのエンティティがありEmailます。

  1. それぞれに多くのMember可能性があります AuthenticationTokens
  2. それぞれに1 つまたは 0AuthenticationTokenがある場合があります Email
  3. それぞれMember0 または 1 PrimaryEmailを持つ場合があります(Emails表から)。本当にこれPrimaryEmailAuthenticationTokens に関連付けられ たものの 1 つですEmail

ので、私は持っています:

public class Member {
    public int MemberId { get; set; }
    public int? PrimaryEmailId { get; set; }
    public virtual Email PrimaryEmail { get; set; }
    public virtual ICollection<AuthenticationToken> AuthenticationTokens { get; set; }
}

public class AuthenticationToken {
    public int AuthenticationTokenId { get; set; }
    public int MemberId { get; set; }
    public virtual Member Member { get; set; }
    public virtual Email Email { get; set; }
}

public class Email {
    public int EmailId { get; set; } // is same as AuthenticationTokenId that the email associated with it
}

上記で説明した設計では、Member と AuthenticationToken を追加できますが、E メールを Member または AuthenticationToken (またはその両方) に添付したい場合、次のエラーが発生します。

INSERT ステートメントが FOREIGN KEY 制約などと競合しました。

このデザインは正しいですか???目的を達成するためにテーブル (およびエンティティ) を設計するにはどうすればよいですか? また、エンティティをコード ファーストでマップするにはどうすればよいでしょうか。アイデアはありますか?

ここに画像の説明を入力

4

1 に答える 1

1

私は個人的に EF 4.1 の流暢な API を使用してすべてのエンティティを構成していますが、既定の規則では理解できないと感じたので、流暢な API を使用して回答します。

モデルを設定する方法は次のとおりです。

public class Member
{
    public Member()
    {
        AuthenticationTokens = new List<AuthenticationToken>();
    }

    public int MemberId { get; set; }

    public virtual Email PrimaryEmail { get; set; }
    public virtual ICollection<AuthenticationToken> AuthenticationTokens { get; set; }
}

public class AuthenticationToken
{
    public int AuthenticationTokenId { get; set; }

    public virtual Email Email { get; set; }
}

public class Email
{
    public int EmailId { get; set; }
}

そして、これは私のコンテキストと流暢な構成です:

public class ExampleApplicationContext : DbContext
{
    public ExampleApplicationContext()
        : base("ExampleApplicationConnection")
    {

    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        // No cascade on delete because the primary email may be held by an authentication token.
        modelBuilder.Entity<Member>()
            .HasOptional(x => x.PrimaryEmail)
            .WithOptionalDependent()
            .Map(x =>
            {
                x.MapKey("EmailId");
            })
            .WillCascadeOnDelete(false);

        // Cascade on delete because an authentication token not associated with a Member makes no sense.
        modelBuilder.Entity<Member>()
            .HasMany(x => x.AuthenticationTokens)
            .WithRequired()
            .Map(x =>
            {
                x.MapKey("MemberId");
            })
            .WillCascadeOnDelete();

        // No cascade on delete because an email may be held by a Member.
        modelBuilder.Entity<AuthenticationToken>()
            .HasOptional(x => x.Email)
            .WithOptionalDependent()
            .Map(x =>
            {
                x.MapKey("EmailId");
            })
            .WillCascadeOnDelete(false);
    }

    public DbSet<Member> Members { get; set; }
}

ここでは、なぜこのように設計したのかについて、私の推論を説明するために最善を尽くします。まず第一に、あなたのモデルMemberではルート集約 (他のエンティティのボス) であるべきだと思われます。私が言いたいのは、Authentication Tokenそれが特定の に属していない限り意味がないということMemberです。また、 anは、 a に属しているか、または an にEmail属していない限り、単独では意味がありません。このため、にはそれが何にアタッチされているかを調べるためのプロパティがありません(これを調べるには、そのコレクションを見るだけでなく、最初に and が必要です)。基本的に、すべてはオブジェクトを中心に展開します。がないと作成できません。そして aまたは anなしでは作成できません。MemberAuthenticationTokenAuthenticationTokenMemberMemberMemberMemberAuthenticationTokenMemberAuthenticationTokenEmail

EF 4.1 の流暢な API にどれだけ慣れているかは完全にはわかりません。質問がある場合はコメントを残してください。できる限りお答えします。上記のモデルを構築および検証するために使用した小さなサンプル アプリケーションも含めました。プログラム (小さなコンソール アプリ) を実行する場合は、SQL Server のインスタンスを指すように App.config の接続文字列を変更するだけです。

私が懸念していることの 1 つは、 がaと an のEmail両方に属することができるという事実です。私の懸念は、いくつかの興味深いカスケード削除をセットアップしなければならなかったという事実から来ています。ただし、すべての要件を把握しているわけではありません。このセットアップは問題なく機能しているように見えるため、問題にはならない可能性があります。MemberAuthenticationToken

コンソール アプリケーションの例

于 2011-12-19T01:07:06.950 に答える