EF5和循环或多个级联路径,FOREIGN KEY [英] EF5 And cycles or multiple cascade paths, FOREIGN KEY

查看:77
本文介绍了EF5和循环或多个级联路径,FOREIGN KEY的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一个比较棘手的问题,我已经知道为什么通常会发生此异常,以及如何通过在其中一个属性中将WillCascadeOnDelete设置为False来解决该异常.

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 :

成员:

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

并在MemberConfiguration中:

and in MemberConfiguration :

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

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

        });

如您所见,邮件中有一个具有ForeignKey SenderID(一对多双向)的发件人. 会员有2条消息列表,其中1条为收件人,1条为发件人. 我试图在其中一个关系(第一个)中禁用级联删除 但是我仍然从SQL引擎得到同样的问题. 我也尝试从消息部分而不是从成员部分定义关系 与:

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)

推荐答案

这应该可以正常工作(与您拥有的相同)

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

这篇关于EF5和循环或多个级联路径,FOREIGN KEY的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆