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