2013-04-04 120 views
2

我遇到了一個奇怪的問題,我已經知道爲什麼正常發生此異常以及如何通過Disablaing WillCascadeOnDelete在其中一個屬性中將其解決爲False。EF5和週期或多個級聯路徑,FOREIGN KEY

但我的問題似乎是其他種類, 這裏是我的代碼:

Memeber:

public class Memeber 
     { 
     public int MemberID { get; set; } 
     public virtual ICollection<Message> SentMessages { get; set; } 
     public virtual ICollection<Message> RecievedMessages { get; set; } 
     } 

    public class Message 
    { 
     public long MessageID { get; set; } 
     public int SenderMemberId{ get; set; } 
     public virtual ICollection<Member> RecipientsMembers { get; set; } 
     [ForeignKey("SenderMemberId")] 
     public virtual Member SenderMember { get; set; } 
    } 

這裏是映射: 在消息組態:

this.HasRequired(c => c.SenderMember) 
      .WithMany(c => c.SentMessages) 
      .HasForeignKey(c => c.SenderMemberId) 
      .WillCascadeOnDelete(false); 

並在成員配置中:

this.HasMany(c => c.RecievedMessages) 
     .WithMany(c => c.RecipientsMembers) 

     .Map(cm => 
     { 
      cm.ToTable("MessageJoinMemeber"); 
      cm.MapLeftKey("MessageId"); 
      cm.MapRightKey("MemberId"); 

     }); 

正如你看到一個消息hase發件人與ForeignKey SenderID,一對多bidirrectional。 和成員有兩個消息列表作爲收件人和一個列表作爲發件人。 我試圖禁用級聯刪除其中一個關係(第一個) 但我仍然從SQL引擎得到同樣的問題。 此外,我試圖定義從消息部分的關係,而不是從體部 有:

 this.HasMany(c => c.RecipientsMembers) 
       .WithMany(c=> c.RecievedMessages) 
       .Map (cm => 
       { 
       cm.ToTable("MessageJoinMemeber"); 
       cm.MapLeftKey("MessageId"); 
       cm.MapRightKey("MemberId"); 

       }); 

但百達我得到這個錯誤:

System.Data.SqlClient.SqlException was unhandled by user code 
    HResult=-2146232060 
    Message=Introducing FOREIGN KEY constraint 'FK_dbo.MessageJoinMemeber_dbo.Messages_MemberId' on table 'MessageJoinMemeber' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints. 
Could not create constraint. See previous errors. 
    Source=.Net SqlClient Data Provider 
    ErrorCode=-2146232060 
    Class=16 
    LineNumber=1 
    Number=1785 
    Procedure="" 
    Server=KINGPC 
    State=0 
    StackTrace: 
     at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) 
     at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) 
     at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) 

回答

3

這應該工作正常(它是相同作爲你有)

public class Member 
{ 
    public int MemberID { get; set; } 
    public string Name { get; set; } 
    public virtual ICollection<Message> SentMessages { get; set; } 
    public virtual ICollection<Message> RecievedMessages { get; set; } 
} 
public class Message 
{ 
    public long MessageID { get; set; } 
    public int SenderMemberId { get; set; } 
    public virtual ICollection<Member> RecipientsMembers { get; set; } 
    [ForeignKey("SenderMemberId")] 
    public virtual Member SenderMember { get; set; } 
} 
... 
protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
modelBuilder.Entity<Message>() 
    .HasRequired(c => c.SenderMember) 
    .WithMany(c => c.SentMessages) 
    .HasForeignKey(c => c.SenderMemberId) 
    .WillCascadeOnDelete(false); 

modelBuilder.Entity<Member>() 
    .HasMany(c => c.RecievedMessages) 
    .WithMany(c => c.RecipientsMembers) 
    .Map(cm => 
    { 
     cm.ToTable("MessageJoinMemeber"); 
     cm.MapLeftKey("MessageId"); 
     cm.MapRightKey("MemberId"); 

    }); 
... 
var member = new Member { Name = "sender1" }; 
db.Messages.Add(new Message 
{ 
    SenderMember = new Member { Name = "sender1" }, 
    RecipientsMembers = new List<Member> 
    { 
     new Member { Name = "receiver1" }, 
     new Member { Name = "receiver2" }, 
     new Member { Name = "receiver3" }, 
    } 
}); 
db.SaveChanges(); 

......但如果你仍然有問題,你可以使連接表手動...

// public virtual ICollection<Message> RecievedMessages { get; set; } 
public virtual ICollection<MessageJoinMember> Recieved { get; set; } 
... 
// public virtual ICollection<Member> RecipientsMembers { get; set; } 
public virtual ICollection<MessageJoinMember> Recipients { get; set; } 
... 
public class MessageJoinMember 
{ 
    public long MessageID { get; set; } 
    public Message Message { get; set; } 
    public int MemberID { get; set; } 
    public Member Member { get; set; } 
} 
... 
modelBuilder.Entity<Message>() 
    .HasRequired(c => c.SenderMember) 
    .WithMany(c => c.SentMessages) 
    .HasForeignKey(c => c.SenderMemberId) 
    .WillCascadeOnDelete(false); 
modelBuilder.Entity<MessageJoinMember>() 
    .HasKey(x => new { x.MessageID, x.MemberID }); 
modelBuilder.Entity<MessageJoinMember>() 
    .HasRequired(x => x.Message) 
    .WithMany(x => x.Recipients) 
    .HasForeignKey(x => x.MessageID) 
    .WillCascadeOnDelete(false); 
modelBuilder.Entity<MessageJoinMember>() 
    .HasRequired(x => x.Member) 
    .WithMany(x => x.Recieved) 
    .HasForeignKey(x => x.MemberID) 
    .WillCascadeOnDelete(false); 
// remove the implicit many-to-many here 
... 
var message = new Message { SenderMember = new Member { Name = "sender1" }, }; 
db.MessageJoinMembers.Add(new MessageJoinMember { Message = message, Member = new Member { Name = "receiver1" } }); 
db.MessageJoinMembers.Add(new MessageJoinMember { Message = message, Member = new Member { Name = "receiver2" } }); 
db.MessageJoinMembers.Add(new MessageJoinMember { Message = message, Member = new Member { Name = "receiver3" } }); 
db.Messages.Add(message); 
db.SaveChanges(); 
+0

而且我需要將此MessagejoinMembers添加到我的DbContext? – 2013-04-04 16:30:04

+0

只要這個模型不需要(你給我在這裏)。兩者都可以工作 - 而且這種方法很好(上面的部分 - 例如'解決方案') - 我沒有看到任何問題,這與我在幾個地方使用的完全相同。如果你有一些錯誤 - 那麼這是別的給你的錯誤。 – NSGaga 2013-04-04 16:46:38

+0

但是,我給了你第二個選擇 - 以防萬一 - 這很好 - 因爲它越複雜,如果你真的擁有所有的表並擁有對字段的訪問權,就會更容易處理。還有'性能方面',談論總是'fk領域'的定義,因爲這使事情變得更快 - 我猜這也w /索引/連接表。 – NSGaga 2013-04-04 16:47:59

相關問題