C# 实体框架代码表之间的前两个关系

C# 实体框架代码表之间的前两个关系,c#,sql,entity-framework,code-first,C#,Sql,Entity Framework,Code First,我有两张桌子有点问题 第一个表是关于用户的,有-用户ID、用户名、密码等 第二个是处理消息,因此它有-messageId、senderId、receiverId、messageContent 如您所见,senderId和receiverId都需要与users表中的userId相关 但当我试图首先使用代码时,它就崩溃了。 我得到一个异常: [ForeignKey("Sender")] public int SenderId { get; set; } public vi

我有两张桌子有点问题

  • 第一个表是关于用户的,有-
    用户ID、用户名、密码等

  • 第二个是处理消息,因此它有-
    messageId、senderId、receiverId、
    messageContent

如您所见,
senderId
receiverId
都需要与users表中的userId相关

但当我试图首先使用代码时,它就崩溃了。 我得到一个异常:

    [ForeignKey("Sender")]
    public int SenderId { get; set; }
    public virtual User Sender { get; set; }

    [ForeignKey("Receiver")]
    public int ReceiverId { get; set; }
    public virtual User Receiver { get; set; }
在表“Messages”上引入外键约束“FK_dbo.Messages_dbo.Users_ReceiverId”可能会导致循环或多个级联路径。请在“删除无操作”或“更新无操作”时指定,或修改其他外键约束

这就是我在消息类中建立关系的方式:

    [ForeignKey("Sender")]
    public int SenderId { get; set; }
    public virtual User Sender { get; set; }

    [ForeignKey("Receiver")]
    public int ReceiverId { get; set; }
    public virtual User Receiver { get; set; }
有什么想法吗?我现在被卡住了。如果我先在数据库中运行它,效果会非常好,但如果我先尝试编写代码,效果会非常好。

在Migrations文件夹中生成的.cs文件中,将cascadeDelete:true替换为cascadeDelete:false,例如:

AddForeignKey("dbo.Messages", "ReceiverId", "dbo.Users", "Id", 
    cascadeDelete: true);
AddForeignKey("dbo.Messages", "SenderId", "dbo.Users", "Id", 
    cascadeDelete: true);
变成:

AddForeignKey("dbo.Messages", "ReceiverId", "dbo.Users", "Id", 
    cascadeDelete: false);
AddForeignKey("dbo.Messages", "SenderId", "dbo.Users", "Id", 
    cascadeDelete: false);

默认情况下,EF代码首先在外键表的删除和更新规则上创建设置为true的级联选项。您可以在SQLServerManagementStudio中对此进行检查,方法是右键单击表的外键列,然后展开“插入和更新规范”。

要快速解决此问题,只需在DBContext.cs或YourContext.cs类中添加此代码,您可以在这些类中设置DBSet信息

 protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {            
        modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

    }
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{            
modelBuilder.Conventions.Remove();
}

从项目的Package manager控制台窗口运行Add Migration InitialContext命令和Update Database-Verbose命令。

我想您的答案在这篇文章中

它表示还有另一个名为InverseAttrivuteProperty的装饰器,它可以帮助您定义origin表中关系的哪一端与destiny表中的哪一端匹配

但是,不要按照解释使用它。我不得不把你的装饰师留在外键上


只是测试了一下,效果不错。很快我会发布一些解释。

只需手动配置实体关系,以避免对EF造成混淆

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{            
    modelBuilder.Entity<Message>()
                .HasOptional(x => x.Sender)
                .WithMany(x => x.SenderMessages);
    modelBuilder.Entity<Message>()
                .HasOptional(x => x.Reciever)
                .WithMany(x => x.RecieverMessages);

}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{            
modelBuilder.Entity()
.has可选(x=>x.Sender)
.具有多个(x=>x个发送消息);
modelBuilder.Entity()
.has可选(x=>x.receiver)
.具有多条(x=>x.receiveMessages);
}

对于记录,如果我只对其中一个字段使用外键(例如,仅对发件人使用外键),则它可以完美地工作。但是,receiver字段的名称可能会很奇怪,比如“receiver\u User\u UserId”。。。