当两个类之间有多个不同的(一对多、多对多)关系时,如何注释模型类



我正在尝试将代码优先和数据注释与EF 6.0一起使用,并使用以下非常简单的两个类的模型:基本上是可以作为活动组织者和参与者的员工:

public class Employee
{
    [Key]
    public Guid Id { get; set; }
    public string name { get; set; }
    public virtual ICollection<Event> event { get; set; }
}
public class Event
{
    [Key]
    public Guid Id { get; set; }
    public string name { get; set; }
    [ForeignKey("organizer")]
    public Guid organizerId { get; set; }
    public virtual Employee organizer { get; set; }
    public virtual ICollection<Employee> atendees { get; set; }
}

当我让EF从这些类生成数据库时,它出人意料地没有生成Employee和Event之间的多对多关系(因此,没有EmployeeEvent多对多表),而是在Employees中生成事件id外键。(我不知道为什么。)

当然,我可以通过使用fluent API直接创建正确的数据库映射,但我想知道是否有一种方法可以通过数据注释实现这一点。

我认为Employee organizer与EF混淆了,这就是为什么EF认为你有一对多的关系;如果是这种情况,那么你可以使用InverseProperty来解决它,正如@Corak所说的

public class Employee
{
    [Key]
    public Guid Id { get; set; }
    public string name { get; set; }
    [InverseProperty("atendees")]
    public virtual ICollection<Event> event { get; set; }
}
public class Event
{
    [Key]
    public Guid Id { get; set; }
    public string name { get; set; }
    [ForeignKey("organizer")]
    public Guid organizerId { get; set; }
    public virtual Employee organizer { get; set; }
    [InverseProperty("event")]
    public virtual ICollection<Employee> atendees { get; set; }
}

这应该足以在没有Fluent API的情况下解决问题

有关InverseProperty的更多信息,您可以查看以下答案

您所描述的模型对您来说可能很简单,但从数据库设计的角度来看,它并不那么微不足道,这就是EF无法正确导出"显而易见"配置的原因。

首先,实际上EmployeeEvent之间有两种关系:

(1) 一对多员工->描述员工正在组织的事件的事件
(2) 多对多员工->描述员工参加的事件

所以模型应该是这样的:

public class Employee
{
    [Key]
    public Guid Id { get; set; }
    public string name { get; set; }
    public virtual ICollection<Event> organizingEvents { get; set; }
    public virtual ICollection<Event> attendingEvents { get; set; }
}
public class Event
{
    [Key]
    public Guid Id { get; set; }
    public string name { get; set; }
    [ForeignKey("organizer")]
    public Guid organizerId { get; set; }
    public virtual Employee organizer { get; set; }
    public virtual ICollection<Employee> attendees { get; set; }
}

另一个问题是,这种模型产生了循环级联删除问题的可能性。说到限制,级联选项不能用数据注释指定,所以它确实需要一个流畅的配置。不管怎样,一旦它需要它,为什么要麻烦数据注释呢,让我们用流利的API:来完全配置关系

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Employee>()
        .HasMany(e => e.organizingEvents)
        .WithRequired(e => e.organizer)
        .HasForeignKey(e => e.organizerId)
        .WillCascadeOnDelete(false);
    modelBuilder.Entity<Employee>()
        .HasMany(e => e.attendingEvents)
        .WithMany(e => e.attendees);
}

作为@Ivan Stoev的回答,您也可以使用流利的API。如果您真的想通过数据注释来实现这一点,您可以为中间的表提供一个类,并且可以使用一对多关系进行映射。尝试以下操作:

 public class Employee
    {
        [Key]
        public Guid Id { get; set; }
        public string name { get; set; }
        public virtual ICollection<middle_table> Middle_table{ get; set; }
        public virtual ICollection<Event> event { get; set; }
    }
    public class Event
    {
        [Key]
        public Guid Id { get; set; }
        public string name { get; set; }
        [ForeignKey("organizer")]
        public Guid organizerId { get; set; }
        public virtual Employee organizer { get; set; }
        public virtual ICollection<middle_table> Middle_table{ get; set; }
    }
    public class your_middle_class
    {
    public Guid Id { get; set; }
    public virtual Employee organizer { get; set; }
     public virtual Event Event{ get; set; }
    }

最新更新