我有一个相当简单的查找表
public class LookupType : Entity
{
public LookupType()
{
}
public LookupType(string value)
{
Value = value;
}
public string Value { get; set; }
// A few other properties
}
和一些从它继承的类
public class SomeType : LookupType
{
public SomeType()
{
}
public SomeType(string value)
: base(value)
{
}
}
我还为OnModelCreating
方法中的LookupTypes提供了以下映射。
// Lookup Types
modelBuilder.Entity<LookupType>()
.Map<SomeType>(m => m.Requires("LookupType").HasValue("Some Type"));
现在它可以很好地完成我需要它做的事情。迁移将创建表,并将列LookupType
作为鉴别符。
CreateTable(
"dbo.LookupTypes",
c => new
{
Id = c.Int(nullable: false, identity: true),
DisplayOrder = c.Int(nullable: false),
Value = c.String(),
TimeStamp = c.Binary(nullable: false, fixedLength: true, timestamp: true, storeType: "rowversion"),
LookupType = c.String(maxLength: 128),
})
.PrimaryKey(t => t.Id);
然而,我需要前缀我的表名。因此,在我的上下文的OnModelCreating
方法中,我添加了以下行
modelBuilder.Types().Configure(entity => entity.ToTable("abc_" + entity.ClrType.Name));
创建迁移时,LookupType
列现在消失了。
CreateTable(
"dbo.abc_LookupType",
c => new
{
Id = c.Int(nullable: false, identity: true),
DisplayOrder = c.Int(nullable: false),
Value = c.String(),
TimeStamp = c.Binary(nullable: false, fixedLength: true, timestamp: true, storeType: "rowversion"),
})
.PrimaryKey(t => t.Id);
我知道前缀配置是导致问题的行,因为注释它并重新生成迁移将使LookupType列返回。
列定义不应该改变,那么为什么要删除鉴别符列呢?有什么方法可以让我保留鉴别符列并在表前加上前缀吗?
我认为你需要在OnModelCreating中指定每层表(TPH)继承:
public class FooDb : DbContext
{
public FooDb()
: base("name=DefaultConnection")
{ }
public DbSet<BarTypeA> BarTypesA { get; set; }
public DbSet<BarTypeB> BarTypesB { get; set; }
public DbSet<BarTypeC> BarTypesC { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Foo>()
.Map<LookupType>(m => m.Requires("xyx" + "FooType").HasValue("L"))
.Map<BarTypeA>(m => m.Requires("xyx" + "LookupType").HasValue("A"))
.Map<BarTypeB>(m => m.Requires("xyx" + "LookupType").HasValue("B"))
.Map<BarTypeC>(m => m.Requires("xyx" + "LookupType").HasValue("C"));
}
}
对象图看起来像这样,并填充数据(未使用seed方法):
public class Foo
{
public int Id { get; set; }
public int DisplayOrder { get; set; }
public string Description { get; set; }
public string Package { get; set; }
public Byte[] TimeStamp { get; set; }
}
public class LookupType : Foo
{
public LookupType(){}
public LookupType(string value)
{
Description = value;
}
public string Description { get; set; }
// A few other properties
}
public class BarTypeA : LookupType
{
public BarTypeA() { }
public BarTypeA(string value) : base(value) { }
}
public class BarTypeB : LookupType
{
public BarTypeB() { }
public BarTypeB(string value) : base(value) { }
}
public class BarTypeC : LookupType
{
public BarTypeC() { }
public BarTypeC(string value) : base(value) { }
}
控制台应用程序
static void Main(string[] args)
{
using (var db = new FooDb())
{
List<Foo> foos = new List<Foo>(){
new BarTypeA ("peanutsA"){ DisplayOrder=100,Package="packA"},
new BarTypeA ("olivesA"){ DisplayOrder = 101,Package="packB" },
new BarTypeB ("peanutsB"){ DisplayOrder = 200,Package="packC" },
new BarTypeB ("olivesB"){ DisplayOrder = 201,Package="packD" },
new BarTypeC ("peanutsC"){ DisplayOrder = 300,Package="packE" },
new BarTypeC ("olivesC"){ DisplayOrder = 301,Package="packF" }
};
db.BarTypesA.Add((BarTypeA)foos[0]);
db.BarTypesA.Add((BarTypeA)foos[1]);
db.BarTypesB.Add((BarTypeB)foos[2]);
db.BarTypesB.Add((BarTypeB)foos[3]);
db.BarTypesC.Add((BarTypeC)foos[4]);
db.BarTypesC.Add((BarTypeC)foos[5]);
db.SaveChanges();
}
Console.WriteLine("Press any key to end");
Console.ReadLine();
}
生成的表在db中:Id、DisplayOrder描述、包、时间戳xyxFooType, xyxLookupType
1 100 NULL packA NULL NULL A
2 101 NULL packB NULL NULL A
3 200 NULL packC NULL NULL B
4 201 NULL packD NULL NULL B
5 300 NULL packE NULL NULL C
6 301 NULL packF NULL NULL C
,最后add-migrations initialSetup看起来像这样:
CreateTable(
"dbo.Foos",
c => new
{
Id = c.Int(nullable: false, identity: true),
DisplayOrder = c.Int(nullable: false),
Description = c.String(),
Package = c.String(),
TimeStamp = c.Binary(),
xyxFooType = c.String(maxLength: 128),
xyxLookupType = c.String(maxLength: 128),
})
.PrimaryKey(t => t.Id);
希望微软能找到完整的文档和提供示例的资源,因为EF看起来是如此强大。不确定上述是否适合您的场景,但它肯定会生成一个有用的Discriminator列xyzLookupType。db-migration files-debug/obj缓存不同步。仍在寻找好的文档/书籍。不完全理解为什么Description没有被添加到表中,这可能是因为我添加了BarTypes而不是根类型(可能需要虚拟属性)。也可能需要为祖先添加dbset…
显然,如果实体框架不切换到Table Per Type,你就不能在Table Per Hierarchy继承上指定任何自定义映射细节。
最简单的修复就是添加.ToTable("abc_LookupTypes")
// Lookup Types
modelBuilder.Entity<LookupType>()
.Map<SomeType>(m => m.Requires("LookupType").HasValue("Some Type"))
.ToTable("abc_LookupTypes");
然后实体框架切换回TPH。上面的行是冗余的,但它可以工作,而不必在Context文件中添加继承的类型。