Я разрабатываю какую-то CMS, где у меня есть иерархия разных типов контента.
Базовый класс содержимого:
[Table("Content")]
public abstract class CmsContent {
public string Content { get; set; }
public abstract CmsContentType Type { get; }
public CmsContentLocation Location { get; set; }
public CmsContent()
{ }
}
CmsContentType
- это перечисление:
public enum CmsContentType: byte {
None = 0,
Text = 1,
News = 2,
Document = 3,
Link = 4,
Image = 5,
Banner = 6
}
Букет конкретных типов контента наследуется от CmsContent
таких как TextContent
, ImageContent
и т.д.
public class TextContent: CmsContent {
public override CmsContentType Type {
get { return CmsContentType.Text; }
}
public TextContent()
{ }
}
Все эти данные хранятся в одной таблице.
Контекст Entity Framework (упрощен):
public class EFDbContext: DbContext {
public DbSet<CmsContent> Content { get; set; }
public EFDbContext() { }
public EFDbContext(string connectionString)
: base(connectionString) { }
protected override void OnModelCreating(DbModelBuilder mb) {
mb.Entity<CmsContent>()
.Map<TextContent>(m => m.Requires("Type").HasValue(1))
.Map<NewsContent>(m => m.Requires("Type").HasValue(2))
.Map<DocumentContent>(m => m.Requires("Type").HasValue(3))
.Map<LinkContent>(m => m.Requires("Type").HasValue(4))
.Map<ImageContent>(m => m.Requires("Type").HasValue(5))
.Map<BannerContent>(m => m.Requires("Type").HasValue(6));
}
}
Проблема в том, что когда я пытаюсь выбрать поле "Тип", я получил ошибку.
Мой репозиторий с запросом:
public class EFCmsContentRepository: EFRepository<CmsContent>, ICmsContentRepository {
protected override DbSet<CmsContent> Table {
get { return Context.Content; }
}
public CmsContent Find(CmsContentType type) {
return Table.FirstOrDefault(c => c.Type == type);
}
}
Сообщение об ошибке, которое я получил:
Указанный тип типа "Тип" не поддерживается в LINQ to Entities. Поддерживаются только инициализаторы, сущности и свойства навигации сущности.
Я использую EF 5, где поддерживаются запросы enum, и у меня есть другой репозиторий, где я успешно выбираю поле enum.
Любая помощь приветствуется. Заранее спасибо.
Наконец, чтобы решить проблему, я удалил поле Type
из каждой модели. Поскольку hvd сказал, что мы не должны управлять свойствами за EF назад. Более того, поля db таблицы, используемые для сопоставления иерархии (Type
в моем случае), не должны определяться в модели. Чтобы узнать тип контента, мы можем использовать Reflection (однако он редко нуждался в хорошей архитектуре).
enum
; у вас возникнет та же проблема, если вы измените ее на использованиеint
. Исключением является отсутствие установщика свойств и ваша попытка управлять свойством за спиной EF. (Я публикую это как комментарий, а не как ответ, потому что простого знания того, что не так, недостаточно, чтобы знать, как изменить ваш код, и я не уверен, какой самый подходящий метод будет здесь.)