Entity Framework 4.1 RC: код первый вопрос наследования EntityTypeConfiguration - PullRequest
11 голосов
/ 08 апреля 2011

Я пытаюсь использовать общий класс EntityTypeConfiguration для настройки первичного ключа для всех моих сущностей, чтобы каждый производный класс конфигурации не повторялся.Все мои сущности реализуют общий интерфейс IEntity (который говорит, что у каждой сущности должно быть свойство Id типа int).

Мой базовый класс конфигурации выглядит следующим образом:

public class EntityConfiguration<TEntity> : EntityTypeConfiguration<TEntity>

    where TEntity : class , IEntity {

    public EntityConfiguration() {

        HasKey( e => e.Id );

        Property( e => e.Id ).HasDatabaseGeneratedOption( DatabaseGeneratedOption.Identity );

    }

}

Каждая сущностьзатем имеет свой собственный класс конфигурации, расширяющий этот класс следующим образом:

public class CustomerConfiguration : EntityConfiguration<Customer> {

    public CustomerConfiguration() : base() {

        // Entity specific configuration here

    }

}

Он прекрасно компилируется, но проблема, с которой я сталкиваюсь, заключается в том, что во время выполнения я получаю следующее исключение, возникающее при попытке создания EF 4.1 RCмодель:

System.InvalidOperationException не обработано. Message = Ключевой компонент 'Id' не является объявленным свойством типа 'Customer'.Убедитесь, что он не был явно исключен из модели и является допустимым примитивным свойством.Source = EntityFramework

Если я изменю класс CustomerConfiguration для расширения от EntityTypeConfiguration и повторю конфигурацию первичного ключа, то он работает нормально, но я теряю возможность использовать общую конфигурацию (принцип DRY являетсямотивация).

  • Я что-то здесь не так делаю?
  • Есть ли другой способ поделиться общей конфигурацией между сущностями?

Для справки здесьдругие участвующие классы:

public interface IEntity {

    int Id { get; set; }

}

public class Customer : IEntity {

    public virtual int Id { get; set; }

    public virtual string name { get; set; }

}

Спасибо!

Ответы [ 4 ]

12 голосов
/ 11 апреля 2011

Похоже, что эти конфигурации имеют некоторые проблемы с интерфейсом.Это работает, если вы измените IEntity на EntityBase:

public class EntityBase
{
    public virtual int Id { get; set; }
}

public class Customer : EntityBase
{
    public virtual string Name { get; set; }
}

public class EntityConfiguration<TEntity> : EntityTypeConfiguration<TEntity>
    where TEntity : EntityBase
{
    public EntityConfiguration()
    {
        HasKey(e => e.Id);
        Property(e => e.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
    }
}

public class CustomerConfiguration : EntityConfiguration<Customer>
{
    public CustomerConfiguration()
        : base()
    {
        ...
    }
}
2 голосов
/ 08 апреля 2011

Я не думаю, что вам нужно пройти через все это.EF 4.1 Code First использует много соглашений о конфигурации, и благодаря этому свойство Id объекта настраивается в качестве первичного ключа.Таким образом, внедряя интерфейс IEntity в ваших сущностях, вы настраиваете их с Id в качестве первичного ключа.

Вот ссылка на блог команды ADO.NET, в котором объясняется, как работает соглашение о первичных ключах - Соглашения для Code First

1 голос
/ 22 марта 2012

Вы можете просто создать статический метод в классе и передать в него сущность. Например:

public class CustomerConfiguration : EntityConfiguration<Customer>
{
    public CustomerConfiguration()
        : base()
    {
        ...
        EntityConfiguration.Configure(this);
    }
}

public static class EntityConfiguration
{
    public static void Configure<TEntity>(EntityTypeConfiguration<TEntity> entity) where TEntity : EntityBase
    {
        entity.HasKey(e => e.Id);
        entity.Property(e => e.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
    }
}
0 голосов
/ 04 декабря 2012

У меня похожая проблема с EF5.0, когда у меня есть общий абстрактный класс со свойством Id и реализацией для абстрактных членов и самоопределяемых свойств.Похоже, код структуры сущности сначала ищет только сопоставленные свойства класса.Я пытался использовать отражатель - кажется, я прав, но не уверен в этом на 100%.

И, к счастью, нашел решение для этого:

 protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {                
            modelBuilder.Conventions.Remove<IncludeMetadataConvention>();
            modelBuilder.Entity<MyEntity>()
               .Map(m =>
               {
                   **m.MapInheritedProperties();**                   
               });
        }

, поэтому вмой случай: чтобы отобразить также свойства из базового класса, я должен добавить одну строку кода m.MapInheritedProperties () ...

...