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; }
}
当您有一个外键并且外键列不可为空时(意味着,必需)。 EF 将自动尝试在关系上启用级联删除。在您的情况下,它将尝试为两个外键列启用级联删除,并且它们都指向同一个用户 table!这就是您收到此错误的原因。如果您有一个 UserContact 记录,其中 UserId
和 ContactID
都指向同一个用户记录怎么办。级联删除现在很困惑:)
此外,由于一个用户可以有多个联系人,我们需要用户 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。
我目前正在学习 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; }
}
当您有一个外键并且外键列不可为空时(意味着,必需)。 EF 将自动尝试在关系上启用级联删除。在您的情况下,它将尝试为两个外键列启用级联删除,并且它们都指向同一个用户 table!这就是您收到此错误的原因。如果您有一个 UserContact 记录,其中 UserId
和 ContactID
都指向同一个用户记录怎么办。级联删除现在很困惑:)
此外,由于一个用户可以有多个联系人,我们需要用户 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。