【问题标题】:ASP.NET Model RelationshipASP.NET 模型关系
【发布时间】:2016-01-09 16:45:25
【问题描述】:

我目前正在学习 ASP.NET MVC 和 Web API。

我正在尝试创建用户模型。用户可以拥有任意数量的 UserContact。 UserContacts 引用作为联系人的用户和作为联系人的用户。我制作了一个名为 UserContact 的模型,因为附加到此模型的是附加信息。

public class User
{
    public int UserID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class UserContact
{
    public int UserContactID { get; set; }

    public int UserID { get; set; }
    [ForeignKey("UserID"), Column(Order = 0)]
    [Required]
    public User User { get; set; }

    public int ContactID { get; set; }
    [ForeignKey("ContactID"), Column(Order = 1)]
    [Required]
    public User Contact { get; set; }

    public DateTime ContactSince { get; set; }
}

所以这给了我一个关于级联删除的错误。如何建立这样的关系,其中两个外键指向相同的模型类型?我还没有掌握实体框架的语法。如果我在 User 模型中没有 ICollection UserContacts,这是否会妨碍我获取与该用户关联的 UserContacts 的能力?

【问题讨论】:

    标签: asp.net-web-api ef-code-first


    【解决方案1】:

    当您有外键并且外键列不可为空时(意味着,必需)。 EF 将自动尝试在关系上启用级联删除。在您的情况下,它将尝试为两个外键列启用级联删除,并且它们都指向同一个用户表!这就是您收到此错误的原因。如果您有一条 UserContact 记录,其中 UserIdContactID 都指向相同的用户记录。级联删除现在很困惑:)

    此外,由于一个用户可以拥有多个联系人,因此我们需要在 User 表上使用 Contacts 属性来表示这一点。这将是 UserContact 的集合。此用户也可以是许多其他人的联系人。所以让我们为此创建另一个属性。

    public class User
    {
        public int UserID { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    
        public ICollection<UserContact> Contacts { set; get; } 
        public ICollection<UserContact> ContactOf { set; get; }
    }
    
    public class UserContact
    {
        public int UserContactID { get; set; }
    
        public int UserID { get; set; }
        public User User { get; set; }
    
        public int ContactID { get; set; }
        public User Contact { get; set; }
    
        public DateTime ContactSince { get; set; }
    }
    

    在您的 DbContext 类中,我们可以配置外键关系并告诉 EF 使用覆盖的 OnModelCreating 方法中的流利配置禁用级联删除。下面的代码将禁用这两个关系的级联删除。但是为了你的错误消失。禁用一个外键就足够了。

    public class YourDbContext: DbContext
    {       
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<UserContact>()
              .HasRequired<User>(g=>g.User)
              .WithMany(g=>g.Contacts)
              .HasForeignKey(g=>g.UserID)
              .WillCascadeOnDelete(false);
    
            modelBuilder.Entity<UserContact>()
              .HasRequired<User>(g => g.Contact)
    
              .WithMany(g => g.ContactOf)
              .HasForeignKey(g => g.ContactID)
              .WillCascadeOnDelete(false); // this one is not really needed to fix the error
    
            base.OnModelCreating(modelBuilder);
        }
    
        public DbSet<User> Users { set; get; } 
        public DbSet<UserContact> UserContacts { set; get; } 
    }
    

    这将使用必要的外键创建您想要的表。

    【讨论】:

    • 谢谢,这正是我想要的。
    • 不客气!我在答案中添加了更多细节。
    【解决方案2】:

    EF 没有足够的信息来确定另一端的关系,所以是的,您需要集合。您可以使用 InverseProperty 注释来澄清(或流畅的 api 语句):

    public class User
    {
        public int UserID { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    
        [InverseProperty("User")]
        public Virtual ICollection<UserContact> Users{ get; set; }
        [InverseProperty("Contact")]
        public Virtual ICollection<UserContact> Contacts { get; set; }
    }
    
    public class UserContact
    {
        public int UserContactID { get; set; }
    
        public int UserID { get; set; }
        [ForeignKey("UserID"), Column(Order = 0)]
        [Required]
        public User User { get; set; }
    
        public int ContactID { get; set; }
        [ForeignKey("ContactID"), Column(Order = 1)]
        [Required]
        public User Contact { get; set; }
    
        public DateTime ContactSince { get; set; }
    }
    

    http://www.entityframeworktutorial.net/code-first/inverseproperty-dataannotations-attribute-in-code-first.aspx

    【讨论】:

    • 仍然收到此错误:在表 'UserContacts' 上引入 FOREIGN KEY 约束 'FK_dbo.UserContacts_dbo.Users_ContactID' 可能会导致循环或多个级联路径。指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。无法创建约束。查看以前的错误。
    • 产生错误的代码是什么?这是一个真正的参照完整性错误,您要删除父级而不删除子级?另请注意,EF 中的级联删除与 SQL Server 级联删除不同。
    • 在Package Manager Console中使用Update-Database时出现错误
    • 在关闭级联删除的情况下查看 Shyju 的流畅代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-16
    • 1970-01-01
    • 1970-01-01
    • 2018-02-25
    • 1970-01-01
    • 2017-10-13
    相关资源
    最近更新 更多