帮助使用EF4.1流畅的API映射域模型?

时间:2011-06-20 15:27:14

标签: entity-framework-4.1 fluent-interface

我是EF和流畅API的新手。我的DBA决定他想在公民身份表中绘制一个具有Is_Primary标志的人的“主要”公民身份。所以我们的DB看起来像这样:

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

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

1 个答案:

答案 0 :(得分:0)

无法将域模型提案映射到给定的表结构。在我看来,从域名的角度来看,将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讨论的一些食物。