如何在每个层次表(TPH)映射中共享公共列名 [英] How to share common column names in a Table per Hierarchy (TPH) mapping

查看:100
本文介绍了如何在每个层次表(TPH)映射中共享公共列名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Entity Framework 4 CTP5代码第一种方法,并且我有一个Table Hierarchy(TPH)映射。我的某些类在层次结构中具有共同的属性。

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

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

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

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

默认约定将其映射到以下列:




  • Id

  • 第1条

  • 第2条

  • Customer1

  • Customer2

  • 制造商

  • 订单

  • 类型



我想让EF4共享共同的属性,最终得到以下结果:




  • ID

  • 文章

  • 客户

  • 制造商

  • 订单

  • 输入



减少列数,这具有能够基于文章搜索记录的优点,例如,而不必知道哪些类型具有文章属性。



I尝试将每个公共属性映射到同一列:

  modelBuilder.Entity< B>()。属性(n => n .Article).HasColumnName( 条); 
modelBuilder.Entity< C>()。Property(n => n.Article).HasColumnName(Article);

但这会抛出以下异常:


指定的模式无效。错误:(36,6):错误0019:类型中的每个属性名称必须是唯一的。属性名称文章已经定义。


有谁知道如何解决这个验证规则?

解决方案

绕过此验证没有解决方法。在TPH中,列属于所有子节点继承的基类,或专用于子类。你不能指示EF将它映射到你的两个孩子,而不是另一个。尝试这样做(例如在A.Customer和B.Customer上放置 [Column(Name =Customer)] 将导致元数据异常此消息:


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





TPH解决方案:



一个解决方案是促进客户 code>属性到基类:

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

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

public class B:BaseType {}

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

哪些结果是所需的模式:








TPT解决方案(推荐):



说,我建议考虑使用表格类型(TPT),因为它更适合您的方案:

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

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

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

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

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

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

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


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:

  • Id
  • Article1
  • Article2
  • Customer1
  • Customer2
  • Manufacturer
  • Order
  • Type

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

  • Id
  • Article
  • Customer
  • Manufacturer
  • Order
  • Type

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:

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?

解决方案

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:

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.


TPH Solution:

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 Solution (Recommended):

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

这篇关于如何在每个层次表(TPH)映射中共享公共列名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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