【问题标题】:Entity Framework 6 Code First Fluent API Table MappingEntity Framework 6 Code First Fluent API 表映射
【发布时间】:2015-08-18 23:00:54
【问题描述】:

我在现有数据库中有一个表,如下所示:

PK
FK
Col1
Col2
Col3
Col4
Col5

我需要将它放入这样的类层次结构中:

public abstract class BaseClass : Entity
{
    public int PK {get; set;}
    public string Col1 {get; set;}
}

public class Child1 : BaseClass
{
    public string Col2 {get; set;}
    public string Col3 {get; set;}
}

public class Child2 : BaseClass
{
    public string Col4 {get; set;}
    public string Col5 {get; set;}
}

我目前正在使用 Fluent API 来配置实体,如下所示:

public abstract class BaseClassConfig<TEntity> : EntityTypeConfiguration<TEntity> where TEntity : Entity
{
    public BaseClassConfig()
    {
        ToTable("TheTableName");
        HasKey(x => x.Id);

        Property(x => x.Col1).HasColumnName("SomeName");
    }
}

public class Child1Config : BaseClassConfig<Child1>
{
    public Child1Config()
    {
        Property(x => x.Col2).HasColumnName("SomeName");
        Property(x => x.Col3).HasColumnName("SomeName");
    }
}

public class Child2Config : BaseClassConfig<Child2>
{
    public Child2Config()
    {
        Property(x => x.Col4).HasColumnName("SomeName");
        Property(x => x.Col5).HasColumnName("SomeName");
    }
}

当我将这些添加到上下文中时,继承自 DbContext:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Configurations.Add(new Child1Config());
    modelBuilder.Configurations.Add(new Child2Config());
}

我收到以下错误:

实体类型“Child1”和“Child2”不能共享表“TheTableName” 因为它们不在同一类型层次结构中或没有有效的 与匹配主键的一对一外键关系 他们。

我看过这篇文章:http://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/implementing-inheritance-with-the-entity-framework-in-an-asp-net-mvc-application

但它并没有真正谈论使用fluent api来配置类型,而是直接通过DbSet&lt;&gt;将它们添加到上下文中。

如何使用 fluent api 设置单个表以通过基类映射到不同的类?

【问题讨论】:

  • 为什么要将实体类拆分为三个类?同样,当您在抽象 BaseClassConfig 中定义表名并在其他两个 ChildConfig 类中实现它时,这并没有说明要在数据库中映射的实际实体。你怎么称呼这些配置?如果您想要表结构,则 child2 类应从子 1 继承并将 ToTableName 调用移动到 Child2Config
  • @SandeepKumar - 因为BaseClassChild1Child2 具有共同的属性,而它们每个都有自己的属性,彼此不相关。它是最简单形式的继承。但在这种情况下,现有模式的所有属性都存储在同一个表中。
  • 对于 EF,实体应该映射到数据库表。 EF 代码的目的首先是将实体关联到数据库表,并且实体应仅用于此目的。如果你打算对这个类层次结构做一些事情,那么首先你为表创建一个简单的实体,然后你必须用这个层次结构创建其他类(如 DTO)并在你的应用程序中使用它们。使用自动映射器或创建映射方法来处理从 DTO 到实体的请求。这会将您的应用程序特定责任从实体转移到 DTO。

标签: c# entity-framework


【解决方案1】:

我经常参考的一个很好的参考是这篇 MSDN 文章:Configuring/Mapping Properties and Types with the Fluent API

您将在其中看到对每层次表 (TPH) 继承模式的引用。本质上,您缺少的是 discriminator 字段(并且基于错误,FK 也未映射)。

默认情况下,判别器列名为Discriminator,但从文章中可以看出,这可以在代码优先映射中自定义:

modelBuilder.Entity<Course>()  
    .Map<Course>(m => m.Requires("Type").HasValue("Course"))  
    .Map<OnsiteCourse>(m => m.Requires("Type").HasValue("OnsiteCourse"));

在上面的示例中,Type 是鉴别器,它允许 EF 知道要实现哪个实体类型,即当 Type == "Course" 时实体 Course

【讨论】:

  • 好的,但是如何使用fluent api 将Child2 上的属性描述给EF?为流畅的配置使用继承模式不是一个好主意吗?
  • 我不会尝试对映射配置使用继承。按照惯例,属性将被正确映射,但如果您需要自定义它,您可以在每个派生类型的 Map lambda 中进行。看看这里的答案是否有帮助:stackoverflow.com/questions/23366489/…
  • 为我指明了正确的方向,您的回答也帮助了我。非常感谢!但是还有一个问题,如何标记 fluent api 中所需的派生类型属性?我注意到 Property() 函数在 map 函数中是不同的。
猜你喜欢
  • 2013-05-20
  • 1970-01-01
  • 2014-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-09
相关资源
最近更新 更多