EF Code First реализовал свойство интерфейса - PullRequest
3 голосов
/ 26 марта 2012

У меня есть следующая модель.

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();

Однако я получаю следующее исключение:

Свойство навигации «Ключевые слова» не является объявленным свойством типа 'Foo'. Убедитесь, что он не был явно исключен из модели и что это допустимое свойство навигации.

Что я могу сделать, чтобы этот метод расширения работал?

Ответы [ 3 ]

2 голосов
/ 26 марта 2012

После игры с этим сам я думаю, что вы не будете. Это ограничение или ошибка в свободном API EF. В вашем методе расширения вы отображаете не Foo, а IKeywordEntity, и отображение повреждено. Есть две проблемы - EF не любит интерфейсы, но даже если вы измените свой дизайн и используете абстрактный интерфейс вместо интерфейса, он будет работать для простых свойств, но все равно не будет работать для свойств навигации. По крайней мере, это то, что я получаю из своих собственных экспериментов.

2 голосов
/ 28 марта 2012

Прочитав ответ Ладислава, я решил вручную написать выражение.

    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();
    }
0 голосов
/ 26 марта 2012

Несмотря на то, что я не уверен, что именно здесь написано в вашем коде (я понимаю, что вам нужно) - например, что делает EntityBase и есть ли у вас ключевые слова, «реализованные» внутри него
Вы бынужно убедиться, что ваше свойство каким-то образом сопоставлено (и фактически реализовано)
Я думаю, вы идете к модели TPC - что означает что-то вроде этого ...

modelBuilder.Entity<Foo>().Map(x =>
{
  x.MapInheritedProperties();
  x.ToTable("Foo");
})

... MapInheritedPropertiesможет привести к «выравниванию» иерархии для «конкретного» типа.
Вам понадобится базовый класс, по крайней мере, абстракция для реализации свойств, и Code First может поднять это.
несколько связанный вопрос ...
Entity Framework 4.1. Код первый: получить все сущности с определенным базовым классом
Короче говоря, я думаю, вам лучше использовать абстрактный класс для этого, но у вас все еще будут некоторыеработать, чтобы сделать - обобщение вещей вокруг кода не является простой причиной многих предостережений.Также вам необходимо уточнить модель наследования, что вы ищете.

...