实体框架:将多个类映射到一个表

时间:2016-04-17 17:27:10

标签: c# entity-framework

我认为这在nhiberate中是可能的,但我的问题是关于实体框架。

在我的数据库模型中 - 我无法修改 - 我有冗余列,我想存储在不同的类中。

示例:

public class DateParams
{
    public DateTime CreationDate { get; set; }
    public DateTime ModificationDate { get; set; }

    // some methods
}

public class Localization
{
    public String EnglishLabel { get; set; }
    public String FrenchLabel { get; set; }

    // some methods
}

然后我会在我的一些模特中使用它们:

public class Account // Localization && DateParams 
{
    public int ID { get; set;  }
    public String Name { get; set; }

    public Localization Localization { get; set; }
    public DateParams DateParams { get; set; }
}

public class Lead // DateParams only
{
    public int ID { get; set; }
    public String Name { get; set; }

    public DateParams DateParams { get; set; }
}

我想要实现的是这样的事情

public class LocalizationMap : EntityTypeConfiguration<Localization>
{
   public LocalizationMap()
   { 
        Property(e => e.EnglishLabel).HasColumnName("en");
        Property(e => e.FrenchLabel).HasColumnName("fr");
   }
}

public class AccountMap : EntityTypeConfiguration<Account>
{
    public AccountMap()
    {            
        HasKey(x => x.ID);
        Property(e => e.Name).HasColumnName("Name");

        HasSubMapping(new LocalizationMap());
        HasSubMapping(new DateParamsMap());

        ToTable("Account");
    }
}

我可以使用继承来解决这个问题,但C#不允许多重继承。

2 个答案:

答案 0 :(得分:4)

您可以通过使用复杂类型来实现此目的。这些映射到名为complextypeName_propertyName的表列,但可以通过覆盖OnModelCreating(DbModelBuilder modelBuilder)中的DbContext来更改此行为,如Entity Framework - Reuse Complex Type

中所述

对于你的例子:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.ComplexType<Localization>();

    modelBuilder.Entity<Account>().Property(x => x.Localization.EnglishLabel).HasColumnName("en");
    modelBuilder.Entity<Account>().Property(x => x.Localization.FrenchLabel).HasColumnName("fr");
    // et cetera
}

答案 1 :(得分:3)

我不会让你开心。

有一个名为 Table Splitting 的EF功能。顾名思义,这允许我们将一个数据库表映射(拆分)到概念模型中的多个类。在您的情况下,Account的映射将如下所示:

class AccountMap : EntityTypeConfiguration<Account>
{
    public AccountMap()
    {
        ToTable("Account");
        HasKey(x => x.ID);
        HasRequired(a => a.DateParams).WithRequiredPrincipal();
        HasRequired(a => a.Localization).WithRequiredPrincipal();
    }
}

class DateParamsMap : EntityTypeConfiguration<DateParams>
{
    public DateParamsMap()
    {
        ToTable("Account");
    }
}

class LocalizationMap : EntityTypeConfiguration<Localization>
{
    public LocalizationMap()
    {
        ToTable("Account");
    }
}

但这会立即显示问题:表格名称&#34;帐户&#34;在类型配置中是硬编码的。对于多种类型,无法重复使用卫星类DateParamsLocalization。而且,在您尝试之前,EF不会接受像DateParams<T>这样的泛型。

这很难过,因为我能想到的所有其他选择都是丑陋的,或充其量只是笨重:

  • 为需要它们的任何实体创建DateParamsLocalization(以及随附配置)的子类。
  • 只需将属性添加到所有类型,并尽可能多地使用投影(因为我认为这项工作的重点是减少您要查询的属性数量。)
  • 使用一个托管没有这些属性的主要类型的上下文和托管卫星类型的第二个上下文(同样,帮助轻松查询较少的属性)。但遗憾的是,您只能从内存中的两个上下文连接实例,即LINQ到对象。
  • 创建第三个卫星类,将两个较小的类组合在一起,并将这三个类用作基类型。