EF4 CTP5, отображающий различные объекты в одну (существующую) таблицу - PullRequest
1 голос
/ 15 января 2011

С помощью подхода, основанного на коде (но с существующей схемой БД), мы пытаемся отобразить 2 разных объекта (Customer и Resource) в одну и ту же таблицу.Обе сущности имеют одинаковые ключи и отображение.

Однако при запуске приложения возникает ошибка во время выполнения, сообщающая нам таинственное сообщение:

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 не могут быть сопоставлены с одной и той же таблицей, поскольку их имена первичных ключей не совпадают.Любая идея, как мы могли бы разные сущности в одной таблице?

Спасибо за вашу помощь

1 Ответ

1 голос
/ 15 января 2011

Для сопоставления 2 сущностей с одной таблицей необходимо создать Сложный тип или Таблица на иерархию (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");
    }
}
...