2011-07-29 252 views
1

我做了簡單的類,模擬我有類(抱歉,我不得不補班,普通的一個例子數據庫沒有我想要的結構詢問):實體框架映射

public class Animal 
{ 
    public System.Guid ID { get; set; } 
    public string SpeciesName { get; set; } 
    public virtual ICollection<AnimalSpecies> AnimalSpecies { get; set; } 
} 

種魚類:

public class Fish 
{  
    public System.Guid ID { get; set; } 
    public int Freshwater { get; set; } 
} 

Spieces爬蟲:

public class Reptile 
{  
    public System.Guid ID { get; set; } 
    public int LifeExpectancy { get; set; }  
} 

AnimalSpecies類:

public class AnimalSpecies 
{ 
    public System.Guid Animal_ID { get; set; } 
    public System.Guid Species_ID { get; set; } 
    public virtual Animal Animal { get; set; } 
} 

的AnimalSpecies的映射:

public AnimalSpeciesMap() 
{  
    this.HasKey(t => new { t.Animal_ID, t.Spieces_ID }); 

    this.Property(t => t.Animal_ID) 
      .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); 
    this.Property(t => t.Spieces_ID) 
      .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); 

    this.ToTable("AnimalSpecies"); 
    this.Property(t => t.Animal_ID).HasColumnName("Animal_ID"); 
    this.Property(t => t.Spieces_ID).HasColumnName("Spieces_ID"); 

    // Relationship between Animal and AnimalSpieces: 
    this.HasRequired(t => t.Animal) 
      .WithMany(t => t.AnimalSpecies) 
      .HasForeignKey(d => d.Animal_ID);    
} 

由於Spieces_ID沒有外鍵,是有辦法來映射AnimalSpecies和魚/爬蟲類之間的關係?

+1

我沒有看到任何錯誤消息,或者您的當前映射的任何樣品。如果你沒有嘗試任何東西,爲什麼我們應該幫助你? –

+0

謝謝,我沒有發佈貼圖,因爲我認爲沒有必要。我應該更好地解釋我的問題。請參閱我對alun的問題的評論,這是我應該問的。 – Minnie

+0

誰又是誰? – Yakimych

回答

3

我不認爲這是可以定義一個映射,其中AnimalSpecies.Species_ID參加在兩個不同關係的外鍵 - 一個AnimalSpeciesFishAnimalSpeciesReptile之間的第二之間。

對我來說,看起來您的型號缺少Species基本類FishReptile。如果你有這樣一個基類模型看起來是這樣的:

public class Animal 
{ 
    public System.Guid ID { get; set; } 
    //... 
    public virtual ICollection<AnimalSpecies> AnimalSpecies { get; set; } 
} 

public class Species // I think the base class could also be abstract 
{ 
    public System.Guid ID { get; set; } 
    //... 
    public virtual ICollection<AnimalSpecies> AnimalSpecies { get; set; } 
} 

public class Fish : Species 
{ 
    public int Freshwater { get; set; } 
} 

public class Reptile : Species 
{ 
    public int LifeExpectancy { get; set; } 
} 

public class AnimalSpecies 
{ 
    public System.Guid Animal_ID { get; set; } 
    public System.Guid Species_ID { get; set; } 
    public virtual Animal Animal { get; set; } 
    public virtual Species Species { get; set; } 
} 

和映射:

public AnimalSpeciesMap() 
{  
    this.HasKey(t => new { t.Animal_ID, t.Spieces_ID }); 

    this.Property(t => t.Animal_ID) 
     .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); 
    this.Property(t => t.Spieces_ID) 
     .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); 

    this.ToTable("AnimalSpecies"); 

    this.HasRequired(t => t.Animal) 
     .WithMany(t => t.AnimalSpecies) 
     .HasForeignKey(d => d.Animal_ID);    

    this.HasRequired(t => t.Species) 
     .WithMany(t => t.AnimalSpecies) 
     .HasForeignKey(d => d.Species_ID);    
} 

如果您AnimalSpecies類沒有其他成員比按鍵,你可以導航屬性還從模型中刪除此類,並映射AnimalSpecies(從域視角來看沒有意義,因爲動物只屬於一個物種,是否它是直接的多對多關係):

public class Animal 
{ 
    public System.Guid ID { get; set; } 
    //... 
    public virtual ICollection<Species> Species { get; set; } 
} 

public class Species // I think the base class could also be abstract 
{ 
    public System.Guid ID { get; set; } 
    //... 
    public virtual ICollection<Animal> Animals { get; set; } 
} 

public class Fish : Species 
{ 
    public int Freshwater { get; set; } 
} 

public class Reptile : Species 
{ 
    public int LifeExpectancy { get; set; } 
} 

// no AnimalSpecies class anymore 

映射:

public AnimalMap() 
{  
    this.HasMany(a => a.Species) 
     .WithMany(s => s.Animals) 
     .Map(x => 
     { 
      x.MapLeftKey("Animal_ID"); 
      x.MapRightKey("Species_ID"); 
      x.ToTable("AnimalSpecies"); 
     }); 
} 

AnimalSpecies現在是由EF用於管理一個隱藏的表中的多對多的關係,並在模型中不被暴露。

我不知道我是否正確理解你的問題。這正是我想到的。

編輯

如果不指定派生類的任何特殊映射EF將承擔TPH(表每層次)繼承,這意味着與基類的所有子一起被存儲在同一個數據庫表中,通過鑑別器列進行區分。

如果您有許多具有許多屬性的派生類,每個更好的繼承策略可能是TPT(Table-Per-Type)。在這種情況下,可以定義每個子類自己的表中的映射:

public FishMap() 
{ 
    this.ToTable("Fishes"); 
} 

public ReptileMap() 
{ 
    this.ToTable("Reptiles"); 
} 

現在每個派生類都有自己的表和基類存儲在表中「種」。 EF將創建相應的數據庫連接時,您查詢例如魚:

var result = context.Species.OfType<Fish>() // Species is DbSet<Species> 
    .Where(f => f.Freshwater == 1).ToList(); 

你可以閱讀更多有關不同繼承映射策略以及它們的優點和缺點在這裏:

+0

非常感謝您花時間思考並提出解決我的問題的想法。你完全理解這個問題。如果物種的數量很少,你的解決方案會很好。我有超過20種不同的物種,每種物種都有至少10種不同的屬性(沒有共同特徵),這就是爲什麼每種物種(魚類和爬行動物)都有它們的表格(如果我在閱讀代碼時錯誤地理解了所有物種在一個物種表中並且沒有單獨的表)。 – Minnie

+0

@Minnie:看我上面的編輯。 TPT(或者TPC)可能是您的模型更好的選擇。 – Slauma

+0

我完全忘記了TPH是默認的映射策略。感謝您的鏈接,我已將Morteza Manavi的文章添加到了我的EF閱讀材料的頂部,並且一直都在回覆他們。非常感謝你的時間,我不得不說,你是真正的靈感,我希望我能學到一些你對EF知道的知識,並可以幫助其他人。我花了很多時間閱讀,並試圖解決我的問題失敗。這是簡單而美妙的解決方案。非常感謝。 – Minnie