c# - 如何在 EF 代码优先中使用 Fluent API 配置 TPH?

标签 c# entity-framework ef-code-first

我有 2 个模型,其中第二个模型继承自第一个模型并具有其他属性:

public class Item
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class ItemMap : EntityTypeConfiguration<Item>
{
    public ItemMap()
    {
        this.ToTable("items");

        this.Map(m => m.Requires("type")
            .HasValue("Type1")
            .IsRequired());

        this.HasKey(t => t.Id).Property(t => t.Id).HasColumnName("id")
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        //Other properties here...
    }
}

public class SecondItem : Item
{
    public string Other { get; set; }
}

public class SecondItemMap : EntityTypeConfiguration<SecondItem>
{
    public SecondItemMap()
    {
        this.Map(m => m.Requires("type")
            .HasValue("Type2")
            .IsRequired());

        //Other properties here...
    }
}

当我运行该应用程序时,出现以下异常:

Map was called more than once for type 'Item' and at least one of the calls didn't specify the target table name.

如何正确映射上述模型?

最佳答案

你应该有这样的东西:

public class BaseClassConfiguration : EntityTypeConfiguration<BaseClass> {
    public BaseClassConfiguration()
        : base() {
        ToTable("BaseClasses", "dbo");

        //HasKey(tp => tp.Id);

        Map<Derived1>(m => m.Requires("dis").HasValue("C"));
        Map<Derived2>(m => m.Requires("dis").HasValue("I"));
        Map<Derived3>(m => m.Requires("dis").HasValue("R"));
        Map<Derived3>(m => m.Requires("dis").HasValue("U"));
    }
}

在哪里

public class Derived1 : BaseClass {}

等等。

========== 完整代码示例 ==========

如您所见,甚至没有配置 DbSet(即公开)。

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.Data.Entity.Core.Metadata.Edm;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.ModelConfiguration;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace testef6 {
    public class Program {
        public static void Main(String[] args) {
            String cs = "Data Source=ALIASTVALK;Initial Catalog=testEF6;Integrated Security=True;MultipleActiveResultSets=True";
            using (TestContext ctx = new TestContext(cs)) {
                ctx.Set<E11>().Add(new E11 { V = "a", V1 ="a1"});
                ctx.Set<E12>().Add(new E12 { V = "b", V2 = "b2" });
                ctx.SaveChanges();
            }

            using (TestContext ctx = new TestContext(cs)) {
                foreach (E1 e in ctx.Set<E1>()) {
                    Console.WriteLine("{0,3}:{1}", e.Id, e.V);
                }
            }            
        }
    }

    public class E1 {    
        public Int32 Id { get; set; }
        public String V { get; set; }
    }

    public class E11 : E1 {
        public String V1 { get; set; }
    }

    public class E12 : E1 {
        public String V2 { get; set; }
    }

    public class E1EFConfiguration : EntityTypeConfiguration<E1> {
        public E1EFConfiguration()
            : base() {
            ToTable("tE1s", "dbo");

            Map<E11>(m => m.Requires("dis").HasValue("E11"));
            Map<E12>(m => m.Requires("dis").HasValue("E12"));

            Property(m => m.V).HasMaxLength(100);
        }
    }

    public class E11EFConfiguration : EntityTypeConfiguration<E11> {
        public E11EFConfiguration()
            : base() {
            Property(m => m.V1).HasMaxLength(150);
        }
    }

    public class E12EFConfiguration : EntityTypeConfiguration<E12> {
        public E12EFConfiguration()
            : base() {
            Property(m => m.V2).HasMaxLength(32);
        }
    }

    public class TestContext : DbContext {
        public TestContext(String cs) : base(cs) {
            Database.SetInitializer<TestContext>(new DropCreateDatabaseAlways<TestContext>());
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder) {          
            modelBuilder.Configurations.Add(new E1EFConfiguration());
            modelBuilder.Configurations.Add(new E11EFConfiguration());
            modelBuilder.Configurations.Add(new E12EFConfiguration());

            base.OnModelCreating(modelBuilder);
        }       
    }
}

关于c# - 如何在 EF 代码优先中使用 Fluent API 配置 TPH?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29982786/

相关文章:

c# - native 窗口 : Release Handle On Close

c# - Entity Framework 如何在其他查询失败时恢复已执行的查询

database - 带有 OLE DB Access 数据源的 ADO.NET Entity Framework

c# - LINQ to Entities 不支持 LINQ 表达式节点类型 'NewArrayBounds'

c# - EntityType 'Uri' 没有定义键

c# - 将项目添加到底层 ObservableCollection 时,递归 TreeView 不保留结构

c# - 如果缺少字段,CsvHelper 将丢弃行

.net - SQL 'time' type in Entity Framework Code First

c# - 将可空引用类型转换为不可空引用类型,更简洁

c# - 类/数据库的循环引用(C#, Entity Framework 代码优先)