ASP.NET模型关系

时间:2016-01-09 16:45:26

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

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

我正在尝试创建用户模型。用户可以拥有任意数量的UserContacts。 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模型中没有UserContacts的ICollection,这是否会阻碍我获取与该用户关联的UserContacts的能力?

2 个答案:

答案 0 :(得分:1)

当您有外键并且外键列不可为空时(表示必需)。 EF将自动尝试在relationshipip上启用级联删除。在您的情况下,它将尝试为两个外键列启用级联删除,并且它们都指向同一个用户表!这就是你得到这个错误的原因。如果您有一个User UserIdContactID的UserContact记录指向同一个用户记录,该怎么办?级联删除现在很困惑:)

此外,由于一个用户可以拥有多个联系人,因此我们需要在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方法中使用fluent配置禁用级联删除。以下代码将禁用两个关系上的级联删除。但是你的错误消失了。禁用一个外键就足够了。

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

这将使用必要的外键创建您想要的表。 enter image description here

答案 1 :(得分:0)

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