当两个类之间存在多个不同(一对多,多对多)关系时,如何对模型类进行注释

时间:2016-03-22 15:30:21

标签: c# asp.net entity-framework data-annotations

我正在尝试将代码优先和数据注释与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多对多表),而是生成一个事件员工中的-id外键。 (我不知道为什么。)

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

3 个答案:

答案 0 :(得分:2)

我认为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 的更多信息,您可以查看this answer

答案 1 :(得分:1)

您所描述的模型对您来说可能看起来很简单,但从数据库设计的角度来看并不是那么简单,这就是为什么EF无法正确推导出明显的&#34;配置。

首先,EmployeeEvent之间实际上有2个关系:

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

所以模型应该是这样的:

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

答案 2 :(得分:0)

作为@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; }
    }