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

14

我认为在 nhibernate 中这是可能的,但我的问题与 Entity Framework 有关。

在我的数据库模型中 - 我无法修改 - 我有一些冗余的列,我希望将它们存储在不同的类中。

例如:

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#中不允许多重继承。


1
也许你应该看一下实体框架复杂类型,例如这里:https://dev59.com/R2LVa4cB1Zd3GeqPtR0F - ChriPf
@ChrifP,您能将您的评论发布为答案,以便我接受吗?我采用了复杂类型的解决方案。 - Akli
2个回答

7

我不会让你感到快乐。

有一个名为表拆分的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");
    }
}

但是,这立刻显示了问题:类型配置中的表名“Account”是硬编码的。没有办法将卫星类和用于多个类型的重复使用。而且,在您尝试之前,EF不接受泛型,如>。
这很遗憾,因为我能想到的所有其他选项都很丑陋,或者最好是笨拙的:
- 为需要它们的任何实体创建DateParamsLocalization的子类(以及相应的配置)。 - 只需将属性添加到所有类型中,并尽可能使用投影(因为我假设此举的整个目的是减少您要查询的属性数量)。 - 使用一个上下文托管不带这些属性的主要类型和第二个上下文托管卫星类型(同样,以便轻松地查询更少的属性)。但不幸的是,您只能在内存中加入来自两个上下文的实例,即LINQ to objects。 - 创建第三个卫星类,将两个较小的类组合起来,并使用这三个类作为基本类型。

6
您可以通过使用复杂类型来实现此功能。这些类型映射到表列,例如complextypeName_propertyName,但是可以通过在DbContext中重写OnModelCreating(DbModelBuilder modelBuilder)来更改此行为,如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
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接