【问题标题】:How to convert persistent entities to concrete types in C#如何在 C# 中将持久实体转换为具体类型
【发布时间】:2016-04-11 18:05:13
【问题描述】:

我有一个如下所示的代码结构。我知道这个例子有点奇怪,但我正在处理的实体在结构上是相似的。

interface IAnimal 
{
    string name {get; set;}
    int Age { get; set;}
    string AnimalType { get; set;}
    ICollection<Dependent> Dependents{get; set;}
}

interface IDependent : IAnimal
{

    string RelationshipToParent{get; set;}
}

class Dependent : IDependent
{
    public string name { get; set;}
    public int Age { get; set;}
    public string AnimalType { get; set;}
    public string RelationshipToParent { get; set;}
    public ICollection<Dependent> Dependents { get; set;}
}

class Animal : IAnimal
{
    public string name { get; set;}
    public int Age { get; set;}
    public string AnimalType{get; set;}
    public ICollection<Dependent> Dependents { get; set;}
}


class Tiger : IAnimal
{
    public string name { get; set;}
    public int Age { get; set;}
    public string AnimalType{get; set;}
    public ICollection<Dependent> Dependents { get; set;}
}

class Dog : IAnimal
{
    public string name { get; set;}
    public int Age{ get; set;}
    public string AnimalType{get; set;}
    public ICollection<Dependent> Dependents{ get; set;}
}

class DogDependent : Dependent
{

}

class TigerDependent : Dependent
{

}

动物可以像任何其他动物一样有家属(例如..老虎可以像狗和大象一样有家属) Animal 和 Dependent 类是 SQL Server 中的持久实体(使用实体框架)。 我的问题是我有大约 20 个这样的具体动物。从 DB 中读取实体后,我需要一种复杂的方法来将 Animal 转换为具体类型,如 Tiger、Dog 等。基于 AnimalType 属性。

例子.. 如果 Animal 对象的 AnimalType 为“Tiger”,则 Animal 应转换为 Tiger 类型(具有所有属性)。家属也是如此,如果该动物类型的 Dependent 是 Dog,则 Dependent 应转换为 DogDependent。

有没有更好的方法来做到这一点,而不是为每种类型编写一个映射器?

【问题讨论】:

  • 请提供某种形式的可编译代码。你有带字段的接口,没有类型的类成员字段等等。很难将伪问题与实际问题区分开来。
  • @grek40 更新了代码
  • 关于您的代码的一些我不明白的地方:接口应该描述行为,即您的对象可以执行的操作。根据这个 Animal 应该是一个类,也许是抽象的。您的具体动物不会在基础动物上添加任何功能,所以我认为没有必要,您可以只使用基础动物并将具体动物作为动物的属性。所有这些都会将上述模型简化为只有两个类。
  • @klink 接口中定义了行为,为了举例,我删除了代码中的函数。

标签: c# .net entity-framework design-patterns


【解决方案1】:

如果我理解正确,您的问题是如何将您的对象模型映射到关系模型,对吗?如果是这种情况,那么有很多模式可以做到这一点。 如果您已经定义了数据模型并且您的所有具体动物(老虎、大象等)都在同一个表中,那么最简单的策略是每个具体类一个表。您所要做的就是添加一个鉴别器列来区分每种类型,并告诉 EF 如何将每条记录映射到基于此的特定类。

有很多文章描述了不同的策略,这是一篇:

http://weblogs.asp.net/manavi/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-1-table-per-hierarchy-tph

【讨论】:

    【解决方案2】:

    您的映射结构将根据每个类型的表或每个层次结构的表而有所不同。

    有没有更好的方法来做到这一点,而不是为每种类型编写一个映射器?

    这取决于,如果您的所有类型都有额外的属性,您将需要映射它们。如果您只想捕获类中的行为但结构相同,则不必映射每种类型。

    这是一个示例,您可以在不同类型中使用单个表。目前,这些类型是使用字符串硬编码来区分类型的。您还可以使用枚举,还可以添加一些反射,以便在运行时根据自定义属性(例如)自动将已知类型及其鉴别器添加到映射中。

    public sealed class DependentMap : EntityTypeConfiguration<Dependent>
    {
        internal DependentMap()
        {
            Map(configuration => configuration.MapInheritedProperties());
            this.ToTable("DependentAnimals").HasKey(t => t.DependentId); // making up some table name and pk here
    
            // mapping types
            // you could probably also map this using reflection if you structure your concrete types to include some type of indicator
            Map<DogDependent>(configuration => configuration.Requires("AnimalType").HasValue("Dog");
            Map<TigerDependent>(configuration => configuration.Requires("AnimalType").HasValue("Tiger");
        }
    }
    

    一些dbContext访问

    db.Set<TigerDependent>().Single(x => name == "Tony the Tiger");
    

    免责声明:我没有对您的接口做任何事情,因为 EF 并非旨在直接使用它们。 EF 的设计是直接使用具体类型(即类)作为模型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多