1

我有3個實體:Member,AuthenticationTokenEmailEF 4.1代碼優先:如何設計和映射這些實體?

  1. 每個Member 5具有許多AuthenticationTokens
  2. 每個AuthenticationToken可具有一個或零Email
  3. 每個Member可以具有零個或一個PrimaryEmail(從Emails表)。 真正的PrimaryEmail是相關Email

AuthenticationToken小號的之一,所以我有:

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 
} 

隨着設計我上面所解釋的,我可以添加會員和AuthenticationToken,但是當我要附上發送電子郵件給會員或AuthenticationToken(或兩者)我給出此錯誤:

The INSERT statement conflicted with the FOREIGN KEY constraint etc.

此設計是否正確? 我如何設計我的表格(和實體)來達到我的目的? 我怎樣才能在我的實體在代碼優先?請問你有什麼想法嗎?

enter image description here

+0

是否將電子郵件中的Id配置爲不自動生成? –

+0

是的!你認爲這種設計是正確的嗎? –

+0

你還配置了EF,EmailId不是自動生成的嗎? –

回答

1

我個人用流利的API在EF 4.1配置我所有的實體時,我不覺得默認的慣例會理解我的,所以我會回答用流利的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是沒有意義的,除非它屬於特定的MemberEmail也沒有意義,除非它屬於Member或屬於AuthenticationToken。由於這個原因AuthenticationToken沒有一個屬性來找出它所附的Member(找到這個你需要一個Member而不僅僅是看它的集合)。基本上,一切都圍繞着Member對象。如果沒有Member,則不能創建AuthenticationToken。如果沒有MemberAuthenticationToken,則不能創建Email

我不完全確定你在EF 4.1中的流暢API有多舒服,所以如果你有任何問題留下評論,我會盡我所能來回答他們。我還包括一個小樣本應用程序,我用它來構建和驗證上面介紹的模型。如果你想運行該程序(它是一個小型的控制檯應用程序),你只需修改App.config中的連接字符串以指向你的SQL Server實例。

有一件我關心的事實是Email可以同時屬於MemberAuthenticationToken。我的擔憂來自於我必須設置一些有趣的級聯刪除。但是,我不知道你的所有要求,而且這個設置看起來很好,所以這可能不是問題。

Example Console Application

+0

剛剛意識到這是一個相當古老的問題。但希望它能幫助別人。 –