ASP.NET 模型关系

ASP.NET Model Relationship

我目前正在学习 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; }
}

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

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

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

此外,由于一个用户可以有多个联系人,我们需要用户 table 上的联系人 属性 来表示。这将是 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 class 中,我们可以配置外键关系并告诉 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; } 
}

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