我知道EF isn't supposed to support generic Entity types但我对项目有很大的需求...... 我有大约200个包含0到5个复杂通用属性的类:
public class MyCommonProperty
{
public virtual string Key { get; set; }
}
public class MyCustomClass<T> : MyCommonProperty where T : struct, IComparable, IFormattable, IConvertible
{
public virtual T Value { get; set; }
public virtual string DisplayValue { get; set; }
public MyCustomClass(string key)
{
Key = key;
}
}
public class ConcreteClass
{
public int Id { get; set; }
public MyCustomClass<CustomType1> CustomType1 { get; set; }
public MyCustomClass<CustomType2> CustomType2 { get; set; }
}
我只想使用这些POCO在具有实体框架的数据库中保留 Key 属性。 这是我的模特:
最后,在我的UI中,代码如下:
using (var db = new ModelContainer())
{
db.ConcreteClassSet.AddObject(new ConcreteClass()
{
CustomType1 = new MyCustomClass<CustomType1>() { Key = "RandomKey1" },
CustomType2 = new MyCustomClass<CustomType2>() { Key = "RandomKey2" }
});
db.SaveChanges();
}
当我运行此代码时,我收到此错误:
具有身份的成员 'Domain.MyCustomClass`1 [[Domain.CustomType1,Domain, Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null]]'没有 存在于元数据集合中。
虽然我的edmx中没有定义 MyCustomClass ,但我不会关心这个类,因为 MyCustomClass 也是 MyCommonProperty wich在元数据中定义......
我在我的容器中覆盖了 ValidateEntity :
public partial class ModelContainer : DbContext
{
public ModelContainer()
: base("name=ModelContainer")
{
}
protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items)
{
if (entityEntry.Entity is ConcreteClass)
return new DbEntityValidationResult(entityEntry, new List<DbValidationError>());
return base.ValidateEntity(entityEntry, items);
}
public DbSet<ConcreteClass> ConcreteClassSet { get; set; }
}
基本上,我关闭了 ConcreteClass 的验证,告诉EF它们始终有效。 通过此解决方法, db.Save()工作:在数据库中,添加了一个新行,在 CustomType1 和 CustomType2 字段。
现在问题是验证:我不想关闭包含这些泛型属性的所有实体的验证 看起来唯一的问题是Entity在元数据中搜索我的属性的具体类型( MyCustomClass )并且找不到它,因为在那里声明的唯一类型是 MyCommonProperty
我认为通过修改元数据可以在其中添加一些假类型。 例如,通过找到 MyCommonProperty ,复制它,并重命名副本'Domain.MyCustomClass`1 [[Domain.CustomType1,Domain,Version = 1.0.0.0,Culture = neutral,PublicKeyToken =空]]'
var metadata = (this as IObjectContextAdapter).ObjectContext.MetadataWorkspace;
var metaType = metadata.GetType("MyCommonProperty", "Domain", DataSpace.CSpace);
metaType.Name = "'Domain.MyCustomClass`1[[Domain.CustomType1, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]'";
metadata.RegisterItemCollection(metaType);
我无法找到一种方法(缺乏知识和技能),所以如果有人有想法或提示,我将不胜感激。