ADO EF代码第一类通用中间类继承映射 [英] ADO EF Code First Generic Intermediate Class Inheritance mapping
问题描述
我有以下要求在OO空间中运行良好,但我似乎无法使用ADO EF代码首先映射回数据库。
我有多种产品,每个都有不同的方面(属性,但不是代码属性的意义)。例如,戒指会有诸如矿物类型=黄金等方面,而钻石将具有清晰度= VVSI1。
正如您所看到的那样,我想要一个增长我的系统的动态方式。
因此,我创建了一个产品类:
public class Product
{
public int id {get;组; }
public string Name {get;组; }
private List< ProductAspect> aspect = new List< ProductAspect>();
public List< ProductAspect>方面{get {return aspects; } set {aspects = value;
它有一个ProductAspect列表,它是所有方面的基类向前移动:
public class ProductAspect
{
public int id {get;组; }
public string AspectName {get;组; }
}
然后,我继承了ProductAspect,使用通用的方式使我成为具体的(强类型)关于我的Aspect值:
public abstract class ProductAspect< T> :ProductAspect
{
public T AspectValue {get;组; }
}
然后我创建一些可以让我装饰我的产品的方面: / p>
public class StringAspect:ProductAspect< string> {};
public class DecimalAspect:ProductAspect< decimal> {};
public class ImageAspect:ProductAspect< byte []> {};
然后我给DbContext一个尝试,并尝试过TPH和TPC继承映射。
似乎没有工作。获取生成的DB模型不会从Aspect Table创建StringAspect或DecimalAspect表的foriegn键。
public class IxamDataContext:DbContext
{
public DbSet< Product>产品{get;组; }
public DbSet< ProductAspect>方面{get;组;
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
AspectMapping(modelBuilder);
}
private void AspectMapping(DbModelBuilder mb)
{
// TPH
//mb.Entity<ProductAspect>()
// .Map< StringAspect>(m => m.Requires(type)。HasValue(sa))
// .Map< DecimalAspect>(m => m.Requires ).HasValue( DA));
// TPC
//mb.Entity<StringAspect>().ToTable(\"StringAspect);
//mb.Entity<DecimalAspect>().ToTable(\"DecimalAspect);
}
}
此种子代码导致以下异常:
产品p = new Product();
p.Name =钻石;
p.Aspects.Add(new StringAspect(){AspectName =History,AspectValue =Old and long});
p.Aspects.Add(new DecimalAspect(){AspectName =Weight,AspectValue = 96.5M});
context.Products.Add(p);
context.SaveChanges();
Excpetion:
EntityType'StringAspect'不在EntitySet
'IxamDataContext.Aspects'中存在
。参数
名称:实体
EF代码中的任何想法首先在那里?
实体框架不支持继承层次结构中的中间非映射类型。这意味着你不能拥有这种继承:A(映射) - > B(未映射) - > C(映射)。 EF也不支持映射通用类型。这意味着您必须从层次结构中删除通用中间类,并将 AspectValue
移动到具有正确类型的派生类型。
I've got the following requirement that works well in the OO space but I can't seem to get it to map back to the DB using ADO EF code first.
I have numrous products each will have different aspects (attributes but not in the sense of code attributes). For instance ring would have aspects such as mineral type = gold etc whilst a diamond would have an aspec of clarity = VVSI1.
As you can see the products very greatly in thier composition and I want a dynamic way of growing my system.
As such I've created a product class:
public class Product
{
public int id { get; set; }
public string Name { get; set; }
private List<ProductAspect> aspects = new List<ProductAspect>();
public List<ProductAspect> Aspects { get { return aspects; } set { aspects = value; } }
}
It has a list of ProductAspect which is the base class for all aspects moving forward:
public class ProductAspect
{
public int id { get; set; }
public string AspectName { get; set; }
}
I then inherit from the ProductAspect using a generic which alows me to be specific (strongly typed) about my Aspect Value:
public abstract class ProductAspect<T> : ProductAspect
{
public T AspectValue { get; set; }
}
I then create some Aspects that will allow me to decorate my product:
public class StringAspect : ProductAspect<string> { };
public class DecimalAspect : ProductAspect<decimal> { };
public class ImageAspect : ProductAspect<byte[]> { };
I then give the DbContext a try and have tried both TPH and TPC inheritance mappings.
Neither seem to work. The DB model that get's generated doesn't create a foriegn key to the StringAspect or DecimalAspect tables from the Aspect Table.
public class IxamDataContext : DbContext
{
public DbSet<Product> Products { get; set; }
public DbSet<ProductAspect> Aspects { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
AspectMapping(modelBuilder);
}
private void AspectMapping(DbModelBuilder mb)
{
//TPH
//mb.Entity<ProductAspect>()
// .Map<StringAspect>(m => m.Requires("type").HasValue("sa"))
// .Map<DecimalAspect>(m => m.Requires("type").HasValue("da"));
//TPC
//mb.Entity<StringAspect>().ToTable("StringAspect");
//mb.Entity<DecimalAspect>().ToTable("DecimalAspect");
}
}
Resulting in the following exception for this Seeding code:
Product p = new Product();
p.Name = "Diamond";
p.Aspects.Add(new StringAspect() { AspectName = "History", AspectValue = "Old and long" });
p.Aspects.Add(new DecimalAspect() { AspectName = "Weight", AspectValue= 96.5M });
context.Products.Add(p);
context.SaveChanges();
Excpetion:
EntityType 'StringAspect' does not exist in the EntitySet 'IxamDataContext.Aspects'. Parameter name: entity
Any ideas from the EF code first pros out there?
Entity framework doesn't support intermediate non mapped types in inheritance hierarchy. It means that you can't have this inheritance: A (mapped) -> B (not mapped) -> C (mapped). EF also doesn't support mapping generic types. It means that you must remove your generic intermediate class from the hierarchy and move AspectValue
to derived types with correct type.
这篇关于ADO EF代码第一类通用中间类继承映射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!