实体框架建模 - 如何建模这个简单的数据结构?

时间:2013-02-06 19:27:14

标签: entity-framework entity-framework-4.1 entity-framework-mapping

Data Structure

这是一个相对简单的数据结构,但我很难找出最好的EF策略来建模它。它显然不是Table Per Hierarchy。所以我尝试了Table Per Type,它不喜欢Client和Person或Customer和Person之间的关系。在阅读了每种混凝土类型表之后,它也没有遵循该模型。那怎么会模拟这个ERD?

更新

它背后的商业用例是我们与几家公司打交道。其中一些公司已经收购了其他公司。母公司(Acme)长期以来一直是客户。儿童公司(Zeta)长期以来一直是客户。当Acme收购Zeta时,他们让一个人负责处理公司(Adam)之间的关系。 Adam现在有2个不同的电子邮件地址,需要通知事件。 adam@acme.com获取客户通知。 adam@zeta.com获取客户通知。这就是我建模的原因。 Adam有点强迫症,喜欢将他的通知分成单个邮箱。作为一名程序员,我不喜欢亚当。 :D

系统中还有其他几种分类,而不是客户和客户。我们还有供应商,技术人员和分销商。我最终建模它与下面的建议非常相似,但将电子邮件表拆分为特定于类型的表(CustomerEmail和ClientEmail)。不完美但是为了“完成它”,它可以工作。

1 个答案:

答案 0 :(得分:3)

  

一个人既可以是客户,也可以是客户。

然后ClientCustomer无法继承Person。您必须使用合成模型进行建模。 Person ClientCustomer相反Person 属性为Client和/或Customer

使用EF,这将是两个一对一的关系:

public class Person
{
    public int PersonId { get; set; }
    public Client Client { get; set; }
    public Customer Customer { get; set; }
}

ClientCustomer可以有一个Person引用,引用回Person。 (它们不需要具有此引用,但通过此导航属性启用对FirstName和LastName的访问是有意义的。)

public class Client / Customer
{
    public int PersonId { get; set; }
    public Person Person { get; set; }
}

我假设一个人不需要总是两个一个Client和一个Customer属性,但有时只有一个(甚至是零?)。在这种情况下,Person是两个关系中的主体,Client / Customer是依赖者:他们必须引用Person,但Person只有可选引用ClientCustomer。使用Fluent API,可以这样建模:

modelBuilder.Entity<Person>()
    .HasOptional(p => p.Client)
    .WithRequired(c => c.Person);

modelBuilder.Entity<Person>()
    .HasOptional(p => p.Customer)
    .WithRequired(c => c.Person);

PersonNote之间的关系是两个普通的一对多关系。 Person可以有两个导航集......

public ICollection<Note> NotesAsNotator { get; set; }
public ICollection<Note> NotesAsNotatee { get; set; }

...和Note可以有两个对Person的引用以及两个外键属性(它们不需要在模型中公开,但通常很有帮助):

public int NotatorIDFK { get; set; }
public Person Notator { get; set; }

public int NotateeIDFK { get; set; }
public Person Notatee { get; set; }

使用Fluent API定义关系如下:

modelBuilder.Entity<Person>()
    .HasMany(p => p.NotesAsNotator)
    .WithRequired(n => n.Notator)
    .HasForeignKey(n => n.NotatorIDFK)
    .WillCascadeOnDelete(false);

modelBuilder.Entity<Person>()
    .HasMany(p => p.NotesAsNotatee)
    .WithRequired(n => n.Notatee)
    .HasForeignKey(n => n.NotateeIDFK)
    .WillCascadeOnDelete(false);

级联删除必须在此处禁用(至少对于两个关系中的一个),否则Person可以通过多个级联删除路径删除Notes,因为这两个关系至少是 - 在SQL Server中 - 禁止。

LocationClient以及LocationCustomer之间的关系再次是两个一对多的关系(总共四个),其中有四个集合在{ {1}}以及LocationLocation中对Client的两次引用。它们的建模与上述关系类似。

CustomerClient以及EmailCustomer之间的关系是一个问题,因为它们是一对一的,但显然是外键{{1} (具有唯一键约束?)(EF不支持)。正如Gert Arnold在评论中已经提到的那样:为什么EmailPersonIDFK之间没有关系?这两种关系是否应该表明一个人可以拥有另一个电子邮件地址作为客户而不是客户?我不明白这部分模型。