【问题标题】:EF4 CTP5, mapping different entities to the same (existing) tableEF4 CTP5,将不同实体映射到同一个(现有)表
【发布时间】:2011-01-17 00:52:33
【问题描述】:

通过代码优先的方法(但使用现有的数据库模式),我们试图将 2 个不同的实体(客户和资源)映射到同一个表。两个实体具有相同的键和映射。

但是,在运行应用程序时,我们遇到了一个运行时错误,告诉我们这条神秘消息:

System.InvalidOperationException: Type 'Resource' cannot be mapped to table 'CLIENT' since type 'Customer' also maps to the same table and their primary key names don't match. Change either of the primary key property names so that they match.    

例子:

 public class EntityA
{
    public string ID { get; set; }
    public string Discriminator { get; set; }
    public string TimeStamp { get; set; }
}
public class EntityB
{
    public string ID { get; set; }
    public string Discriminator { get; set; }
    public string CreatedBy { get; set; }
}
public class EntityAConfiguration : EntityTypeConfiguration<EntityA>
{
    public EntityAConfiguration()
    {
        HasKey(x => new {x.ID, x.Discriminator } );
        Property(x => x.ID).HasColumnName("MyTable_ID").HasDatabaseGenerationOption(DatabaseGenerationOption.None);
        Property(x => x.Discriminator).HasColumnName("MyTable_Discriminator").HasDatabaseGenerationOption(DatabaseGenerationOption.None);            
        Property(x => x.TimeStamp).HasColumnName("MyTable_TimeStamp");
        ToTable("MyTable");
    }
}
public class EntityBConfiguration : EntityTypeConfiguration<EntityB>
{
    public EntityBConfiguration()
    {
        HasKey(x => new { x.ID, x.Discriminator });
        Property(x => x.ID).HasColumnName("MyTable_ID").HasDatabaseGenerationOption(DatabaseGenerationOption.None);
        Property(x => x.Discriminator).HasColumnName("MyTable_Discriminator").HasDatabaseGenerationOption(DatabaseGenerationOption.None);
        Property(x => x.CreatedBy).HasColumnName("MyTable_CreatedBy");
        ToTable("MyTable");
    }
}

上面的代码类似于我们的客户/资源代码(但解释更简单!)。 但是,得到相同的错误消息,告诉我们 EntityA 和 EntityB 不能映射到同一个表,因为它们的主键名称不匹配。

知道我们的映射有什么问题吗? 知道我们如何将不同的实体放到同一个表中吗?

感谢您的帮助

【问题讨论】:

    标签: entity-framework entity-framework-4 code-first ef4-code-only entity-framework-ctp5


    【解决方案1】:

    将 2 个实体映射到一个表需要您创建一个 Complex TypeTable Per Hierarchy (TPH)。您不能像这样将 2 个实体映射到一张表。让我知道哪一个更能描述您的领域模型,我将为您提供所需的对象模型/流式 API 代码。

    更新:TPH 映射:

    public abstract class EntityBase
    {
        [Column(Name = "MyTable_ID")]  
        public string ID { get; set; }
        [Column(Name = "MyTable_Discriminator")]  
        public string Discriminator { get; set; }      
    }
    public class EntityA : EntityBase
    {
        [Column(Name = "MyTable_TimeStamp")]
        public string TimeStamp { get; set; }
    }
    public class EntityB : EntityBase
    {
        [Column(Name = "MyTable_CreatedBy")]
        public string CreatedBy { get; set; }
    }                
    public class StackoverflowTestContext : DbContext
    {
        public DbSet<EntityBase> Entities { get; set; }        
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<EntityBase>()
                        .HasKey(x => new { x.ID, x.Discriminator });
    
            modelBuilder.Entity<EntityBase>()
                        .Map<EntityA>(m => m.Requires("TPHDiscriminator")
                        .HasValue("yourDesiredValueForA"))
                        .Map<EntityB>(m => m.Requires("TPHDiscriminator")
                        .HasValue("yourDesiredValueForB"))
                        .ToTable("MyTable");
        }
    }
    

    【讨论】:

    • 似乎 TPH 可能是这里更好的选择。有了 TPH 和鉴别器,我想我们可以让我们的小例子工作吗?
    • 我也是这么想的。因此,鉴于 TPH 将为您创建一个 Discriminator 列,您是否还需要在 EntityA 和 EntityB 中有一个 Discriminator 属性?
    • 不,我们正在处理现有的数据库模式,我们无法以任何方式改变......
    • 我已经用 TPH 映射更新了答案,看看这个对你有什么影响。
    • 谢谢...我正在我的域 'à l'instant' 中尝试它:-)
    猜你喜欢
    • 2011-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-09
    • 1970-01-01
    • 2013-04-08
    • 2010-10-07
    • 1970-01-01
    相关资源
    最近更新 更多