2011-06-20 31 views
1

我是EF和流利的API的新手。我的DBA決定他想在公民資格表中將一個人的「主要」公民身份與Is_Primary標誌對應起來。因此,我們的數據庫看起來是這樣的:幫助使用EF4.1流利API映射域模型?

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

數據庫表結構是用石頭書寫的嗎?如果是的,你不能改變它,我相信這是沒有希望的。這是'Person'和'Country'之間的多對多關係,對吧?然後,您甚至需要爲您的模型中的實體創建連接表(「Citizenship_Table」),因爲這個「Is_Primary」標誌會創建兩個一對多關係而不是單對多關係。 – Slauma

回答

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討論。

+0

我完全同意你的看法,這就是爲什麼我不希望Is_Primary標誌包含在我的域模型中。由於DBA不想改變他的設計,我試圖想出一個方法來完成這項工作。儘管非常感謝您的輸入!這與我得出的結論幾乎相同,但需要一些確認,以確保我沒有遺漏EF和流利API的某些功能,可能會使其工作。 – RHarris

+0

@RHarris:不幸的是,(理論上)有更多的場景可以*不*映射比可以的場景。物體世界和關係世界之間的「阻抗不匹配」仍然存在,並且可能永遠不會完全消失。這就是爲什麼數據庫管理員最近應該與應用程序/域模型開發人員談論使用ORM的原因。領導層應該在模型設計師手中,而且必須成功使用ORM。如果一個DBA在他的關係世界單獨設計表格,那麼很可能會遇到難以解決的麻煩 - 在我看來。 – Slauma