如何使用Fluent API在EF代码中配置TPH? [英] How to configure TPH using Fluent API in EF code-first?

查看:78
本文介绍了如何使用Fluent API在EF代码中配置TPH?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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);

//其他属性...
}
}

public class SecondItem:Item
{
public string其他{get;组; }
}

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

//其他属性...
}
}

当我运行应用程序时,我得到以下例外:


类型Item并且至少有一个呼叫未指定目标表名称。


如何正确映射上述模型? p>

解决方案

你应该有这样的东西:

  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 ; 
使用System.Collections.Generic;
使用System.ComponentModel.DataAnnotations;
使用System.Data.Entity;
使用System.Data.Entity.Core.Metadata.Edm;
使用System.Data.Entity.Infrastructure;
使用System.Data.Entity.ModelConfiguration;
使用System.Data.Entity.ModelConfiguration.Conventions;
使用System.Linq;
使用System.Text;
使用System.Threading.Tasks;

命名空间testef6 {
public class Program {
public static void Main(String [] args){
String cs =Data Source = ALIASTVALK; Initial Catalog = testEF6; Integrated Security = True; MultipleActiveResultSets = True;
使用(TestContext ctx = new TestContext(cs)){
ctx.Set ()添加(新的E11 {V =a,V1 =a1})
ctx.Set&E12>()。Add(new E12 {V =b,V2 =b2});
ctx.SaveChanges();
}

使用(TestContext ctx = new TestContext(cs)){
foreach(E1 e in ctx.Set< E1>()){
控制台。 WriteLine({0,3}:{1},e.Id,eV);
}
}
}
}

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

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

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

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));

属性(m => m.V).HasMaxLength(100);
}
}

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

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

public class TestContext:DbContext {
public TestContext(String cs):base(cs){
Database.SetInitializer< TestContext> (新的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);
}
}
}


I have 2 models, where the second model inherits from the first one and has additional properties:

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...
    }
}

When I run the app, I get the following exception:

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

How can I map the above models correctly?

解决方案

you should have something like:

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"));
    }
}

where

public class Derived1 : BaseClass {}

and so on.

========== FULL CODE SAMPLE ==========

As you can see, there is not even a DbSet configured (i.e. exposed).

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);
        }       
    }
}

这篇关于如何使用Fluent API在EF代码中配置TPH?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆