【问题标题】:Entity Framework 6 code-first relations with Fluent APIEntity Framework 6 与 Fluent API 的代码优先关系
【发布时间】:2017-05-10 08:06:10
【问题描述】:

我在现有数据库中有 3 个相关表。 Many-to-Many (Many Person Many Group) 和一个表之间 - 事件,女巫 rate 这两个表。

public class Person
    {
        public int PersonID { get; set; }
        public string No { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public virtual ICollection<Event> Events { get; set; }
    }
   public class Event
    {
        public int EventID { get; set; }
        public string EventData { get; set; }
        public int PersonID { get; set; }
        public int GroupID { get; set; }
        public virtual Person Person { get; set; }
        public virtual Group Group { get; set; }
   }

   public class Group
    {
        public int GroupID { get; set; }
        public string GroupName { get; set; }
        public virtual ICollection<Event> PersonGroup { get; set; }
    }

我使用 Fluent API 描述了关系。 首先我声明了PK的

modelBuilder.Entity<Person>()
.HasKey(k => k.PersonID });

modelBuilder.Entity<Event>()
.HasKey(k => k.EventID);

modelBuilder.Entity<Group>()
.HasKey(k => k.GroupID });

现在外键: 人有很多事件

modelBuilder.Entity<Person>()
.HasKey(k => k.PersonID })
.HasMany(k => k.Events)
.WithRequired()
.HasForeignKey(f => f.PersonID);

在 Event 类中,我有 Person(及其所有参数)

modelBuilder.Entity<Event>()
.HasRequired(s => s.Person)
.WithMany()
.HasForeignKey(fk => fk.PersonID);

我还需要一个包含所有数据的组:

modelBuilder.Entity<Event>()
.HasOptional(s => s.Group)
.WithMany()
.HasForeignKey(fk => fk.GroupID });

至少我需要一个参与事件的人员组

modelBuilder.Entity<Group>()
.HasKey(k =>k.GroupID })
.HasMany(k => k.PersonGroup)
.WithOptional()
.HasForeignKey(fk => fk.GroupID);

看来我有我需要的一切,但我需要一个 mo 集合(一组有他们名字的人)

我通过 PersonGroup 关系获得的内容我拥有所有事件,但还需要获取 Persons。你能帮忙吗?

【问题讨论】:

  • 您很可能必须修改模型,而不是询问如何从当前模型中获取信息。我在完善我的答案时意识到了这一点,并在其中加入了一些想法。
  • 我无法更改模型...只需要获取信息...
  • 所以我正在寻找如何在不选择的情况下获取相关数据:) 而这些关系我试图把自己放在
  • 你说的“相关数据没有选择”是什么意思?如果没有任何选择,您的数据模型将不支持 Group.People 集合。在大多数情况下,要求没有技术 XY 的结果是一件相当奇怪的事情。
  • 查看我对客户端便利属性的编辑

标签: c# entity-framework relationship ef-fluent-api


【解决方案1】:

编辑

我只是意识到这不是典型的多对多,因为您的事件组关系是可选的。这是故意的吗?

也许应该更改您的模型以反映更自然的事件结构:

Group-Person:多对多

事件组:多对多

Event-Person:没有直接关系,只能通过组;替代多对多

按照您的模型当前的设计方式,单个事件条目不能与多个组相关,并且一个人和一个人不能成为组的一部分,除非它们在事件条目的上下文中关联.


基本上,您要求的东西不是直接可用的,因为您决定显式创建具有附加属性的多对多表。

但是,在查询中,您始终可以编写一个 select 来获取 people 集合

db.Groups.Select(g => new {Group = g, PeopleInGroup = g.PersonGroup.Select(ev => ev.Person)})

关于您的模型的一些旁注:

  • 考虑删除 EventID 并改用 modelBuilder.Entity&lt;Event&gt;().HasKey(k =&gt; new { k.PersonID, k.GroupID }),就像设计典型的多对多表一样。
  • 在 fluent api 中提及反向属性:

.

modelBuilder.Entity<Person>()
.HasKey(k => k.PersonID })
.HasMany(k => k.Events)
.WithRequired(e => e.Person)
.HasForeignKey(f => f.PersonID);

// redundant with the previous configuration
modelBuilder.Entity<Event>()
.HasRequired(s => s.Person)
.WithMany(p => p.Events)
.HasForeignKey(fk => fk.PersonID);

// same to be done for groups

为了方便地访问组中的相关人员,您可以创建一个未映射的属性 getter 来包装必要的查询:

public class Group
{
    public int GroupID { get; set; }
    public string GroupName { get; set; }
    public virtual ICollection<Event> PersonGroup { get; set; }

    [NotMapped]
    public IEnumerable<Person> PersonsInGroupEvents
    {
        return PersonGroup.Select(ev => ev.Person);
    }
}

// or fluent api way of NotMapped:
modelBuilder.Entity<Group>()
    .Ignore(x => x.PersonsInGroupEvents);

【讨论】:

  • 所以如果不能直接使用,我将使用:db.Groups.Select(g => new {Group = g, PeopleInGroup = g.PersonGroup.Select.....
  • @Sogaila 注意,如果您只对人员集合感兴趣,则不必编写new {...} 部分,这仅与创建组和关联人员之间的关系有关。此外,如果您愿意,可以使用分组或其他查找技术而不是选择。此答案显示了一种查找给定组条目的人员集合的方法,仅此而已。
猜你喜欢
  • 1970-01-01
  • 2018-10-04
  • 2014-01-01
  • 2021-05-04
  • 1970-01-01
  • 2013-01-26
  • 1970-01-01
  • 1970-01-01
  • 2023-01-25
相关资源
最近更新 更多