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

C# 实体框架:将多个类映射到一个表,c#,entity-framework,C#,Entity Framework,我认为这在nhiberate中是可能的,但我的问题是关于实体框架 在我的数据库模型中(我不能修改),我有多余的列,我想存储在不同的类中 例如: public class DateParams { public DateTime CreationDate { get; set; } public DateTime ModificationDate { get; set; } // some methods } public class Localization {

我认为这在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");
    }
}
公共类本地化映射:EntityTypeConfiguration
{
公共本地化地图()
{ 
属性(e=>e.EnglishLabel);
属性(e=>e.FrenchLabel);
}
}
公共类AccountMap:EntityTypeConfiguration
{
公共帐户映射()
{            
HasKey(x=>x.ID);
属性(e=>e.Name);
HasSubMapping(新本地化映射());
HasSubMapping(新的DateParamsMap());
总额(“账户”);
}
}

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

我不会让你高兴的

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

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");
    }
}
class AccountMap:EntityTypeConfiguration
{
公共帐户映射()
{
总额(“账户”);
HasKey(x=>x.ID);
HasRequired(a=>a.DateParams)。WithRequiredPrincipal();
HasRequired(a=>a.Localization)。WithRequiredPrincipal();
}
}
类DateParamsMap:EntityTypeConfiguration
{
公共日期参数映射()
{
总额(“账户”);
}
}
类本地化映射:EntityTypeConfiguration
{
公共本地化地图()
{
总额(“账户”);
}
}
但这立即显示了问题:类型配置中的表名“Account”是硬编码的。无法对多种类型重用附属类
DateParams
Localization
。而且,在您尝试之前,EF不会接受像
DateParams
这样的泛型

这是可悲的,因为我能想到的所有其他选择都是丑陋的,或者说是笨拙的:

  • 为任何需要的实体创建
    DateParams
    Localization
    (以及附带的配置)的子类
  • 只需将属性添加到所有类型中,并尽可能多地使用投影(因为我假设这项工作的全部目的是减少要查询的属性数量)
  • 使用一个上下文托管主类型而不包含这些属性,使用另一个上下文托管附属类型(同样,帮助轻松查询较少的属性)。但不幸的是,您只能将内存中两个上下文中的实例连接起来,即LINQ到对象
  • 创建第三个附属类,合并两个较小的类,并将这三个类用作基本类型

您可以通过使用复杂类型来实现这一点。这些映射到名为
complextypeName\u propertyName
的表列,但可以通过在
DbContext
中覆盖
OnModelCreating(DbModelBuilder modelBuilder)
来更改此行为,如中所述

例如:

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
}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
modelBuilder.ComplexType();
modelBuilder.Entity().Property(x=>x.Localization.EnglishLabel).HasColumnName(“en”);
modelBuilder.Entity().Property(x=>x.Localization.FrenchLabel).HasColumnName(“fr”);
//等等
}

也许您应该看看实体框架复杂类型,例如:@ChrifP,可以将您的评论作为asnwser发布,以便我可以接受吗?我选择了complextype解决方案。