EF Code First实现了接口属性
我有以下型号。
interface IKeywordedEntity { IEntityCollection Keywords { get; } } class Foo : EntityBase, IKeywordedEntity { public virtual IEntityCollection Keywords { get { ... } } } class Bar : EntityBase, IKeywordedEntity { public virtual IEntityCollection Keywords { get { ... } } }
我想编写一个扩展方法,在OnModelCreating
为每个关键字自动处理关键字。
public static void WithKeywords(this EntityTypeConfiguration entityTypeConfiguration) where TEntityType : EntityBase, IKeywordedEntity { entityTypeConfiguration.HasMany(e => e.Keywords).WithMany(); }
所以我在OnModelCreating
调用它。
modelBuilder.Entity.WithKeywords(); modelBuilder.Entity.WithKeywords();
但是,我得到以下exception:
导航属性“关键字”不是“Foo”类型的声明属性。 validation它是否未从模型中明确排除,并且它是有效的导航属性。
我该怎么做才能让这种扩展方法有效?
在玩完这个之后我觉得你不会。 这是EF流畅的API中的限制或错误。 在您的扩展方法中,您不是映射Foo
而是映射IKeywordEntity
,并且映射已损坏。 有两个问题–EF不喜欢接口,但即使你改变你的设计并使用抽象类而不是接口,它也适用于简单的属性,但它仍然不适用于导航属性。 至少这是我从自己的实验中得到的。
在阅读Ladislav的回答后,我决定手动编写表达式。
public static void WithKeywords(this EntityTypeConfiguration entityTypeConfiguration) where TEntityType : EntityBase, IKeywordedEntity { var rootExpression = Expression.Parameter(typeof (TEntityType)); var expression = Expression.Property(rootExpression, "Keywords"); entityTypeConfiguration.HasMany(Expression.Lambda>>(expression, rootExpression)).WithMany(); }
即使我不确定你的代码思路到底是什么(我得到你想要的东西) – 例如EntityBase在做什么,你是否在其中实现了关键词’
您需要确保以某种方式映射属性(并实际实现)
我认为你正在走向TPC模型 – 这意味着像这样……
modelBuilder.Entity().Map(x => { x.MapInheritedProperties(); x.ToTable("Foo"); })
… MapInheritedProperties将为“具体”类型的“层次结构”排序。
你需要一个基类,抽象至少要实现属性,Code First可以选择它。
一个有点相关的问题……
entity framework4.1代码优先:获取具有特定基类的所有实体
简而言之,我认为你最好使用抽象类,但你仍然需要做一些工作 – 首先围绕代码进行概括并不是很容易引起许多警告。 你还需要直接获得你的inheritance模型,你需要的是什么。