2011-07-29 253 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