2011-06-20 4 views
1

私はEFと流暢なAPIを使い慣れていません。私のDBAは、市民権テーブルにIs_Primaryフラグを持つ人物の「プライマリ」市民権をマッピングしたいと考えました。したがって、私たちのDBは次のようになります。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'の多対多の関係ですか?次に、この "Is_Primary"フラグのためにモデル内のエンティティに結合テーブル( "Citizenship_Table")を作成し、多対多の一意ではなく二対多の関係を作成する必要があります。 – Slauma

答えて

0

ドメインモデルの提案を指定されたテーブル構造にマップすることはできません。私の意見では、ドメインの観点からは、Is_PrimaryフラグをCitizenshipテーブル(基本的にはPersonCountryの間の結合テーブル)に導入することも間違っています。

ドメインは、人が主要国籍(または多分なし)が、決して多くを持つことができると言います。これはテーブル構造で正しく表現されていません。Is_Primary列は、特定の人物に対して複数の国に設定することができます。ある国の市民権を変更することも困難です。なぜなら、他の国がプライマリとしてマークされていれば、その人に属する市民権テーブルのすべてのエントリを検索しなければならないからです。 。

これは、PersonCountryテーブル(必須またはオプション)への外部キーを持つ必要があることをモデルで正しく表現しています。第一次国籍を変更するには、この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

@Rハリス:残念ながら、できるシナリオよりもマッピングできない(理論的に)より多くのシナリオがあります。オブジェクト世界とリレーショナル世界との間の「インピーダンス不一致」は依然として存在し、決して完全に消滅することはありません。 ORMの使用については、DBAがアプリケーション/ドメインモデル開発者と話をする必要があります。そしてリーダーシップは、ORMをうまく使用しなければならないモデルデザイナーの手に委ねられるべきです。 DBAがリレーショナル・ワールド内でテーブルを単独で設計する場合、私の意見では、それはマップできないトラブルになる可能性が大きいです。 – Slauma

関連する問題