如何在每个层次结构(TPH)映射表共享公共列名层次、结构、在每个、TPH

2023-09-02 01:40:10 作者:一人摁全场

我使用实体框架4 CTP5 code第一个方法,我有每个层次结构(TPH)映射表。在常见的一些我的班级层次结构中的有属性。

I'm using Entity Framework 4 CTP5 code first approach and I have a Table per Hierarchy (TPH) mapping. Some of my classes in the hierarchy have properties in common.

public class BaseType
{
    public int Id { get; set; }
}

public class A : BaseType
{
    public string Customer { get; set; }
    public string Order { get; set; }
}

public class B : BaseType
{
    public string Customer { get; set; }
    public string Article { get; set; }
}

public class C : BaseType
{
    public string Article { get; set; }
    public string Manufacturer { get; set; }
}

默认的规定,这个映射到下列:

The default convention maps this to the following columns:

标识 第一条 第二条 的customer1 的customer2 制造商 订单 键入

我想有EF4有着共同的属性,以结束与以下内容:

I want to have EF4 share the common properties to end up with the following:

标识 文章 客户 制造商 订单 键入

除了列的数目减少,这具有能够以搜索基于第例如记录,而不必知道哪些类型究竟有一个条属性的优点。

Apart from the reduced number of columns, this has the advantage of being able to search for records based on Article for example, without having to know which types exactly have an Article property.

我试图映射每个公共属性设置为相同的列:

I tried mapping each common property to the same column:

modelBuilder.Entity<B>().Property(n => n.Article).HasColumnName("Article");
modelBuilder.Entity<C>().Property(n => n.Article).HasColumnName("Article");

但这抛出以下异常:

but this threw the following exception:

指定的架构是无效的。错误:(36,6):错误0019:在一个类型的每个属性名称必须是唯一的。物业名称'项目'已经定义。

Schema specified is not valid. Errors: (36,6) : error 0019: Each property name in a type must be unique. Property name 'Article' was already defined.

有谁知道怎么去解决这个验证规则?

Does anyone know how to get around this validation rule?

推荐答案

有没有解决办法绕过这个验证。在TPH列要么是属于哪个是所有孩子的继承或专门的子类的基类。你不能命令EF它映射到你的两个孩子的,但不是其他。尝试这样做(例如通过将 [列(名称为客户)] 两个A.Customer和B.Customer)会造成的 MetadataException 的此消息:

There is no workaround to bypass this validation. In TPH a column is either belongs to the base class which is inherited by all childs or is specialized to the child class. You cannot instruct EF to map it to two of your childs but not for the other. Attempting to do so (for example by putting [Column(Name = "Customer")] on both A.Customer and B.Customer) will be causing a MetadataException with this message:

指定的架构是无效的。错误:   (10,6):错误0019:在一个类型的每个属性名称必须是唯一的。属性名称客户已经定义。

Schema specified is not valid. Errors: (10,6) : error 0019: Each property name in a type must be unique. Property name 'Customer' was already defined.

一个解决方案,这将是推动客户文章属性的基类:

One solution to this would be to promote Customer and Article properties to the base class:

public class BaseType {
    public int Id { get; set; }
    public string Customer { get; set; }
    public string Article { get; set; }
}

public class A : BaseType {
    public string Order { get; set; }
}

public class B : BaseType { }

public class C : BaseType {
    public string Manufacturer { get; set; }
}

这将导致到所需要的模式:

Which results to the desired schema:

不过,我建议考虑使用的表每个类型的(TPT),因为它是一个更适合您的方案:

That said, I recommend to consider using Table per Type (TPT) since it's a better fit for your scenario:

public class BaseType
{
    public int Id { get; set; }
}

public class A : BaseType
{
    [Column(Name = "Customer")]
    public string Customer { get; set; }
    public string Order { get; set; }
}

public class B : BaseType
{
    [Column(Name = "Customer")]
    public string Customer { get; set; }

    [Column(Name = "Article")]
    public string Article { get; set; }
}

public class C : BaseType
{
    [Column(Name="Article")]
    public string Article { get; set; }
    public string Manufacturer { get; set; }
}

public class MyContext : DbContext
{
    public DbSet<BaseType> BaseTypes { get; set; }        

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<BaseType>().ToTable("BaseType");
        modelBuilder.Entity<A>().ToTable("A");
        modelBuilder.Entity<C>().ToTable("C");
        modelBuilder.Entity<B>().ToTable("B");          
    }
}