通过组合上下文将EF 5.0和对象继承映射到同一个表

时间:2013-03-20 12:54:38

标签: c# ef-code-first entity-framework-5 dbcontext

我有一个关于EF 5.0以及将继承对象映射到与超类相同的表的问题。

我的项目如下:

public class ContextA : DbContext
{
    public DbSet<EntityA> EntitiesA { get; set; }
    public DbSet<EntityB> EntitiesB { get; set; }

    public ContextA(string connnectionString) : base(connnectionString) { }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        ModelCreating(modelBuilder);
    }

    public static void ModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<EntityA>().ToTable("EntityAs");
        modelBuilder.Entity<EntityB>().ToTable("EntityBs");

        modelBuilder.Entity<EntityA>().HasKey(e => e.EntityAId);
        modelBuilder.Entity<EntityB>().HasKey(e => e.EntityBId);
    }
}

public class EntityA
{
    public int EntityAId { get; set; }
    public string Name { get; set; }
}

public class EntityB
{
    public int EntityBId { get; set; }
    public string Name { get; set; }

    public int EntityAId { get; set; }
}

太好了。请记住,实体A和B可能位于数据库的不同模式中,或者可能位于不同的上下文中,这是statc ModelCreation方法的原因。

现在我想结合这样的上下文:

public class ContextB : DbContext
{
    public DbSet<EntityAA> EntityAAs { get; set; }
    public DbSet<EntityBB> EntityBBs { get; set; }

    public ContextB(string connnectionString) : base(connnectionString) { }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        ModelCreating(modelBuilder);
    }

    public static void ModelCreating(DbModelBuilder modelBuilder)
    {
        ContextA.ModelCreating(modelBuilder);

        modelBuilder.Entity<EntityAA>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("EntityAs");
        }).HasKey(e => e.EntityAId)
        .Property(e => e.EntityAId)
        .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        modelBuilder.Entity<EntityBB>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("EntityBs");
        })
        .HasKey(e => e.EntityBId)
        .Property(e => e.EntityBId)
        .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        modelBuilder.Entity<EntityAA>()
                    .HasMany(ea => ea.EntityBs)
                    .WithRequired(eb => eb.EntityA)
                    .HasForeignKey(eb => eb.EntityAId);
    }
}

public class EntityAA : EntityA
{
    private readonly List<EntityBB> _entityBbs = new List<EntityBB>();

    public virtual ICollection<EntityBB> EntityBs
    {
        get { return _entityBbs; }
    }
}

public class EntityBB : EntityB
{
    public EntityAA EntityA { get; set; }
}

我想这样做,因为我想拥有特定于架构的上下文,我想将它们组合到一个特定于应用程序的上下文中。

问题是,我在模型创建过程中遇到错误:

Ergebnis Meldung:   Die EfInheritance.Test.GlobalTests.InsertEntitiesContextB-Testmethode hat eine Ausnahme ausgelöst: System.InvalidOperationException: The foreign key component 'EntityAId' is not a declared property on type 'EntityBB'. Verify that it has not been explicitly excluded from the model and that it is a valid primitive property.
Ergebnis StackTrace:    
bei System.Data.Entity.ModelConfiguration.Configuration.Properties.Navigation.ForeignKeyConstraintConfiguration.Configure(EdmAssociationType associationType, EdmAssociationEnd dependentEnd, EntityTypeConfiguration entityTypeConfiguration)
   bei System.Data.Entity.ModelConfiguration.Configuration.Properties.Navigation.NavigationPropertyConfiguration.ConfigureConstraint(EdmAssociationType associationType, EdmAssociationEnd dependentEnd, EntityTypeConfiguration entityTypeConfiguration)
   bei System.Data.Entity.ModelConfiguration.Configuration.Properties.Navigation.NavigationPropertyConfiguration.ConfigureDependentBehavior(EdmAssociationType associationType, EdmModel model, EntityTypeConfiguration entityTypeConfiguration)
   bei System.Data.Entity.ModelConfiguration.Configuration.Properties.Navigation.NavigationPropertyConfiguration.Configure(EdmNavigationProperty navigationProperty, EdmModel model, EntityTypeConfiguration entityTypeConfiguration)
   bei System.Data.Entity.ModelConfiguration.Configuration.Types.EntityTypeConfiguration.ConfigureAssociations(EdmEntityType entityType, EdmModel model)
   bei System.Data.Entity.ModelConfiguration.Configuration.Types.EntityTypeConfiguration.Configure(EdmEntityType entityType, EdmModel model)
   bei System.Data.Entity.ModelConfiguration.Configuration.ModelConfiguration.ConfigureEntities(EdmModel model)
   bei System.Data.Entity.DbModelBuilder.Build(DbProviderManifest providerManifest, DbProviderInfo providerInfo)
   bei System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection)
   bei System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext)
   bei System.Data.Entity.Internal.RetryLazy`2.GetValue(TInput input)
   bei System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
   bei System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)
   bei System.Data.Entity.Internal.Linq.InternalSet`1.Initialize()
   bei System.Data.Entity.Internal.Linq.InternalSet`1.get_InternalContext()
   bei System.Data.Entity.Internal.Linq.InternalSet`1.ActOnSet(Action action, EntityState newState, Object entity, String methodName)
   bei System.Data.Entity.Internal.Linq.InternalSet`1.Add(Object entity)
   bei System.Data.Entity.DbSet`1.Add(TEntity entity)
   bei EfInheritance.Test.GlobalTests.InsertEntitiesContextB() in c:\temp\EfInheritance\EfInheritance.Test\GlobalTests.cs:Zeile 45.

最后,我的问题是:

  1. 可以这样工作吗?
  2. 如果这是一个可能的解决方案,我该怎么办才能让它发挥作用?
  3. 如果我在ModelCreation中注释ForeignKey-Statement,除了运行简单测试后数据库中的结果外,它可以正常工作:

    using (var ctx = new ContextB("CodeFirstDatabase"))
            {
                EntityAA aa = new EntityAA();
                aa.Name = "Test_AA_01";
    
                EntityBB bb = new EntityBB();
                bb.Name = "Test_BB_01";
    
                aa.EntityBs.Add(bb);
    
                ctx.EntityAAs.Add(aa);
    
                ctx.SaveChanges();
            }
    

    EntityBs EntityBId |名称| EntityAId |鉴别者| EntityA_EntityAId 1 | Test_BB_01 | 0 | EntityBB | 1

    EntityAs EntityAId |名称| Disciminator 1 | Test_AA_01 | EntityAA

    现在还有一个我无法访问的额外ForeignKeyColumn以及一个额外的鉴别器列。

    有人知道该怎么做,让这个工作吗?我有项目准备好在必要时邮寄/附加它。

    亲切的问候,

    斯文

0 个答案:

没有答案