【问题标题】:Help mapping Domain model with EF4.1 fluent API?使用 EF4.1 fluent API 帮助映射域模型?
【发布时间】:2011-06-20 15:27:13
【问题描述】:

我是 EF 和 fluent API 的新手。我的 DBA 决定他想在公民身份表中映射一个带有 Is_Primary 标志的人的“主要”公民身份。所以我们的数据库看起来像这样:

**Person Table**
Person_Id    int           identity  (PK)
First_Name   nvarchar(30)
...

**Citizenship_Table**
Citizenship_Person_Id  int identity  (PK)
Person_Id              int
Country_Code           char(2)
Is_Primary             byte
...

**Country_Table**
Country_Code     char(2)  (PK)
Country_Name     varchar(30)
...

我真的不想在我的域模型中使用 Is_Primary 标志。相反,我希望我的域看起来像这样:

public class Person
{
   public int Id {get; set;}
   ...
   public virtual ICollection<Country> Citizenships {get; set;}
   public Country PrimaryCitizenship {get; set;}
}

public class Country
{
   public int Code {get; set;}
   public string Name {get; set;}
}

有没有办法映射这种情况?

【问题讨论】:

  • 数据库表结构是不是一成不变的?如果是并且您无法更改它,我相信没有希望对此进行映射。 PersonCountry 之间是多对多的关系,对吧?然后,由于这个“Is_Primary”标志,您甚至需要将连接表(“Citizenship_Table”)创建到模型中的实体,并创建两个一对多关系而不是单个多对多关系。

标签: entity-framework-4.1 fluent-interface


【解决方案1】:

无法将您的域模型提案映射到给定的表结构。在我看来,从域的角度来看,将Is_Primary 标志引入公民表(基本上是PersonCountry 之间的连接表)也是错误的。

该域表示一个人可以拥有一个主要公民身份(或者可能没有),但不能拥有许多。这在表结构中没有正确表达:Is_Primary 列可以为给定人员设置多个国家/地区。更改一个人的主要公民身份也很困难,因为如果有另一个国家被标记为主要国家,您必须搜索属于该人的公民身份表中的所有条目,然后在为新国家设置标志之前重置此标志.

这在您的模型中正确表达,这意味着Person 应该具有Country 表的外键(必需或可选)。更改主要公民身份只需要将此 FK 设置为另一个值。此模型中不可能出现重复的主标志。

如果您将表结构相应更改为以下...

**Person Table**
Person_Id                int           identity  (PK)
First_Name               nvarchar(30)
PrimaryCountry_Code      char(2)                 (FK to Country table)
...

**Citizenship_Table**
Person_Id                int                     (PK)
Country_Code             char(2)                 (PK)

**Country_Table**
Country_Code             char(2)                 (PK)
Country_Name             varchar(30)
...

...映射到您的模型是可能的:

modelBuilder.Entity<Person>()
    .Property(p => p.Id)
    .HasColumnName("Person_Id");

modelBuilder.Entity<Person>()
    .Property(p => p.Name)
    .HasColumnName("First_Name")
    .HasMaxLength(30);

modelBuilder.Entity<Person>()
    .HasMany(p => p.Citizenships)
    .WithMany()
    .Map(a => {
        a.MapLeftKey("Person_Id");
        a.MapRightKey("Country_Code");
        a.ToTable("Citizenship");
    });

modelBuilder.Entity<Person>()
    .HasOptional(p => p.PrimaryCitizenship) // or .HasRequired(...)
    .WithMany()
    .Map(a => a.MapKey("PrimaryCountry_Code"))
    .WillCascadeOnDelete(false);

modelBuilder.Entity<Country>()
    .HasKey(c => c.Code)
    .Property(c => c.Code)
    .HasColumnName("Country_Code")
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None)
    .HasMaxLength(2)
    .IsFixedLength()
    .IsUnicode(false);

modelBuilder.Entity<Country>()
    .Property(c => c.Name)
    .HasColumnName("Country_Name")
    .HasMaxLength(30)
    .IsUnicode(false);

不是解决您的问题的方法,而是与您的 DBA 讨论的一些食物。

【讨论】:

  • 我完全同意你的看法,这就是为什么我不希望在我的域模型中包含 Is_Primary 标志。由于 DBA 不想改变他的设计,我试图找出一种方法来完成这项工作。非常感谢您的意见!这与我得出的结论几乎相同,但需要一些确认以确保我没有遗漏 EF 和流式 API 的某些功能,这些功能可能允许它工作。
  • @RHarris:不幸的是,(理论上)可以映射的场景比可以映射的场景多得多。对象世界和关系世界之间的“阻抗不匹配”仍然存在,并且可能永远不会完全消失。这就是 DBA 在使用 ORM 时应该与应用程序/域模型开发人员一起讨论的原因。并且领导权应该掌握​​在必须成功使用 ORM 的模型设计者手中。如果一个 DBA 在他的关系世界中单独设计表,那么很有可能会遇到无法映射的麻烦 - 在我看来。
猜你喜欢
  • 2011-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-01
  • 2010-12-21
  • 2011-04-10
  • 1970-01-01
  • 2014-12-09
相关资源
最近更新 更多