实体框架映射

发布于 2024-11-27 02:45:20 字数 1616 浏览 6 评论 0原文

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

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

动物物种类:

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

I've made simple classes that simulate the classes I have (sorry I had to make up the classes, the usual example databases do not have the structure I wanted to ask about):

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

Species Fish:

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

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

Mapping of the 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);               
}

Since Spieces_ID doesn’t have the foreign key, is there a way to map relationship between AnimalSpecies and Fish/Reptile?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

谁与争疯 2024-12-04 02:45:20

我认为不可能定义一个映射,其中 AnimalSpecies.Species_ID 作为外键参与两种不同的关系 - 一种在 AnimalSpeciesFish 之间code> 和 AnimalSpeciesReptile 之间的第二个。

对我来说,您的模型似乎缺少 FishReptileSpecies 基类。如果您有这样的基类,您的模型可能如下所示:

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(每个类型表)。在这种情况下,您在映射中为每个子类定义其自己的表:

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

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

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

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

您可以在此处阅读有关不同继承映射策略及其优缺点的更多信息:

I don't think that it's possible to define a mapping where AnimalSpecies.Species_ID participates as the foreign key in two different relationships - one between AnimalSpecies and Fish and a second between AnimalSpecies and Reptile.

For me it looks like your model is missing a Species base class for Fish and Reptile. If you would have such a base class your model could look like this:

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

And the mapping:

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

If your AnimalSpecies class does not have other members than the keys and navigation properties you could also remove this class from the model and map a direct many-to-many relationship between Animal and Species (doesn't make sense from domain viewpoint because an animal belongs only to one species, does it?):

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

Mapping:

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 is now a hidden table which is managed by EF for the many-to-many relationship and not exposed in the model.

I am not sure if I understand your question correctly. This is just what came to my mind.

Edit

If you don't specify any special mappings for the derived classes EF will assume TPH (Table-Per-Hierarchy) inheritance which means that all subclasses together with the base class are stored in the same database table, distinguished by a discriminator column.

If you have many derived classes with many properties each the better inheritance strategy might be TPT (Table-Per-Type). In this case you define for each subclass its own table in the mapping:

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

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

Now every derived class gets its own table and the base class is stored in table "Species". EF will create the appropriate joins in the database when you query for a fish for example:

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

You can read more about the different inheritance mapping strategies and their benefits and drawbacks here:

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文