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

Akl*_*kli 7 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
}
Run Code Online (Sandbox Code Playgroud)

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

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; }
}
Run Code Online (Sandbox Code Playgroud)

我想要实现的是拥有这样的东西

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");
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Ger*_*old 5

我不会让你开心的。

有一个称为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");
    }
}
Run Code Online (Sandbox Code Playgroud)

但这立即显示了问题:类型配置中的表名“Account”是硬编码的。无法重用卫星类DateParamsLocalization多种类型。而且,在您尝试之前,EF 不会接受像DateParams<T>.

这很可悲,因为我能想到的所有其他选项都是丑陋的,或者充其量是笨重的:

  • 为需要它们的任何实体创建DateParamsLocalization(以及伴随的配置)的子类。
  • 只需将属性添加到所有类型并尽可能多地使用投影(因为我认为这项工作的重点是减少您要查询的属性数量)。
  • 使用一个承载没有这些属性的主要类型的上下文和承载卫星类型的第二个上下文(再次帮助查询较少的属性)。但不幸的是,您只能从内存中的两个上下文中加入实例,即 LINQ to objects。
  • 创建第三个卫星类,组合两个较小的类,并将这三个类用作基本类型。


Chr*_*iPf 5

您可以通过使用复杂的类型来实现。这些映射到表列命名为喜欢的complextypeName_propertyName,但是这种行为可以通过覆盖来改变OnModelCreating(DbModelBuilder modelBuilder)DbContext像描述的实体框架-重用复杂类型

例如:

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
}
Run Code Online (Sandbox Code Playgroud)