实体框架映射

时间:2011-07-29 11:34:04

标签: entity-framework-4.1 code-first

我已经制作了模拟我所拥有的类的简单类(抱歉我必须编写类,通常的示例数据库没有我想要询问的结构):

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 Reptile:

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

动物种类的定位:

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和Fish / Reptile之间的关系?

1 个答案:

答案 0 :(得分:3)

我认为不可能将AnimalSpecies.Species_ID作为外键参与的映射定义为两个不同的关系 - 一个在AnimalSpeciesFish之间,另一个在{{}之间。 1}}和AnimalSpecies

对我而言,您的模型似乎缺少ReptileSpecies的{​​{1}}基类。如果您有这样的基类,您的模型可能如下所示:

Fish

映射:

Reptile

如果您的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); } 和{{之间映射直接的多对多关系1}}(从域观点来看没有意义,因为动物只属于一个物种,是吗?):

AnimalSpecies

映射:

Animal

Species现在是一个隐藏表,由EF管理,用于多对多关系,而不会在模型中公开。

我不确定我是否理解你的问题。这就是我想到的。

修改

如果没有为派生类指定任何特殊映射,EF将假定TPH(Table-Per-Hierarchy)继承,这意味着所有子类与基类一起存储在同一个类中数据库表,由鉴别器列区分。

如果您有许多具有许多属性的派生类,那么更好的继承策略可能是TPT(Table-Per-Type)。在这种情况下,您可以在映射中为每个子类定义自己的表:

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

现在每个派生类都有自己的表,基类存储在表“Species”中。当您查询鱼时,EF将在数据库中创建适当的连接:

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

您可以在此处详细了解不同的继承映射策略及其优缺点: