Entity Framework 4.1 Code First: получение всех сущностей с определенным базовым классом

У меня есть DbContext с настройкой разных DbSet<T> со всеми типами, производными от одного и того же базового класса:

public class Foo : Entity { }
public class Bar : Entity { }

MyDbContext : DbContext
{
  public DbSet<Foo> Foos { get; set; }
  public DbSet<Bar> Bars { get; set; }
}

Можно ли получить все сущности, имеющие класс Entitybase, в одном запросе, например:

DbContext.Set<Entity>();  // doesn't work

Я попытался ввести явное DbSet<Entity> в DbContext, но это привело к созданию одной большой таблицы для всех сущностей в базе данных.

Дополнительный вопрос: если это как-то работает, как насчет запроса интерфейсов?

Изменить:

Я следовал инструкциям на link и сделал мои сопоставления следующим образом:

MyDbContext : DbContext
{
  public DbSet<Entity> Entities { get; set; }

  protected override void OnModelCreating(DbModelBuilder modelBuilder)
  {
    // Foo
    modelBuilder.Entity<Foo>().Map(x =>
    {
      x.MapInheritedProperties();
      x.ToTable("Foo");
    })
    .HasMany(x => x.Tags).WithMany();

    modelBuilder.Entity<Foo>()
        .Property(x => x.Id)
        .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

    // Bar
    // same thing for Bar and a bunch of other Entities

    base.OnModelCreating(modelBuilder);
  }
}

Это выдает ошибку

Свойство «Id» не является объявленным свойством типа «Foo». Убедитесь, что свойство не было явно исключено из модели с помощью метода Ignore или аннотации данных NotMappedAttribute. Убедитесь, что это допустимое примитивное свойство.

Я также попытался явно установить ключ для свойства Id:

modelBuilder.Entity<Foo>().Map(x => {...})
  .HasKey(x => x.Id)
  .HasMany(x => x.Tags).WithMany();

Что мне не хватает?


person davehauser    schedule 28.04.2011    source источник
comment
Взгляните сюда: stackoverflow.com/q/353284/114029   -  person Leniel Maccaferri    schedule 28.04.2011
comment
Спасибо за ссылку. Но похоже, что это ответ с использованием подхода «сначала база данных», тогда как я ищу решение с подходом «сначала код». Может быть, я что-то упускаю здесь, но я не нахожу подсказок для своей проблемы.   -  person davehauser    schedule 28.04.2011


Ответы (2)


Вам необходимо ввести Наследование TPC. После этого DbContext.Set<Entity>() будет работать, и у вас все равно будет таблица для каждой сущности.

person Ladislav Mrnka    schedule 28.04.2011
comment
Спасибо, надеялся, что вы увидите мой вопрос ;-) Похоже на то, что я ищу, но пока не заработало, борюсь с кучей ошибок... прямо сейчас с Свойство 'Id' равно не объявленное свойство типа "Foo".... Id объявлен в базовом классе, есть идеи? - person davehauser; 28.04.2011
comment
Похоже, вы забыли использовать MapInheritedPropeties, но трудно сказать, когда я не вижу ваших сопоставлений. - person Ladislav Mrnka; 28.04.2011
comment
Я только что обновил свой вопрос сопоставлениями, которые пробовал. Не забыл MapInheritedProperties, думаю, я точно следовал инструкциям... Возможно, у меня есть какие-то дополнительные особые требования к моим сущностям... :-) - person davehauser; 28.04.2011
comment
Поскольку это дало мне ответ на мой первоначальный вопрос, я установил его как принятый ответ. Спасибо. - person davehauser; 29.04.2011

Просто к вашей проблеме в разделе «Правка»:

Сообщение об ошибке указывает, что у вас есть ключевое свойство Id в базовом классе Entity. Затем вам нужно настроить ключевое свойство в этом классе, а не в производном классе Foo:

modelBuilder.Entity<Entity>()
    .Property(x => x.Id)
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
person Slauma    schedule 28.04.2011
comment
Имеет смысл. Теперь я получаю следующую ошибку: Тип 'Foo' не может быть отображен как определено, потому что он отображает унаследованные свойства от типов, которые используют разделение сущностей или другую форму наследования. Либо выберите другую стратегию сопоставления наследования, чтобы не сопоставлять унаследованные свойства, либо измените все типы в иерархии, чтобы сопоставлять унаследованные свойства и не использовать разделение. :-) - person davehauser; 28.04.2011
comment
@Dave: Без понятия, я никогда не видел этого исключения. Скорее всего, это связано с этой частью вашего сопоставления foo: .HasMany(x => x.Tags). Что такое Tag? Является ли он также производным от вашего базового класса? Вы также определили сопоставление TPC для этого типа? - person Slauma; 29.04.2011
comment
Хм, другая интерпретация: он отображает унаследованные свойства от типов, которые используют... другую форму наследования Итак, типы, от которых наследуется Foo, являются вашим базовым классом Entity. Этот тип использует другую форму наследования, что может означать, что существует еще один производный от Entity тип Foo2, который не отображает унаследованные свойства. Если вы не настроили сопоставление для Foo2, по умолчанию используется TPH (другая форма наследования), а не TPC. Это может означать, что вам нужно явно настроить TPC для всех типов в иерархии, чтобы избавиться от исключения. - person Slauma; 29.04.2011
comment
@Slauma: Tag также является производным от моего базового класса. У меня также было подозрение, что это может вызвать ошибку, поэтому я попробовал то же самое с типом Tag, который не является производным от Entity. Я определил эти сопоставления для всех своих типов, производных от базового класса (включая Tag). Entity реализует два интерфейса, может в этом проблема? - person davehauser; 29.04.2011
comment
@Dave: я не думаю, что интерфейсы - проблема. Я думаю, вам нужно шаг за шагом упростить свою модель в тестовой среде и посмотреть, когда ошибка исчезнет. Не видя вашей полной модели, трудно сказать, что может быть не так. И, возможно, задайте новый вопрос об этой проблеме, чтобы привлечь больше внимания. - person Slauma; 29.04.2011
comment
@Slauma: Спасибо за ваши усилия! - person davehauser; 29.04.2011