EF5 And cycles or multiple cascade paths, FOREIGN KEY

落爺英雄遲暮 提交于 2019-12-08 02:58:20

问题


I got a wierd problem, i already know about why normaly this exception happen and how to solve it by Disablaing WillCascadeOnDelete to False in one of the properties.

But my problem seems to be other kind, Here is my code :

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; }
    }

And here is the mapping : in Message configuration:

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

and in MemberConfiguration :

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

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

        });

As you see a message hase a sender with ForeignKey SenderID, one to many bidirrectional. and Member has 2 list of messages one as reciever and one list as sender. I tried to disableing cascading on delete in one of those relation(first one) but i still get the same problem from SQL engine. Also i tried to define the relation from Message part and not from member part with :

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

                });

But Allways i get this Error :

 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)

回答1:


This should work fine (it's the same as what you have)

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();

...but if you still have problems you can make the join table manually...

// 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();


来源:https://stackoverflow.com/questions/15812227/ef5-and-cycles-or-multiple-cascade-paths-foreign-key

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!