2011-04-08 107 views
11

我想使用一個普通的EntityTypeConfiguration類來配置我的所有實體的主鍵,以便每個派生的配置類不會重複自己。我的所有實體都實現了一個通用接口IEntity(它表示每個實體必須具有int類型的Id屬性)。實體框架4.1 RC:代碼第一個EntityTypeConfiguration繼承問題

我的配置基礎類看起來是這樣的:

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是 未處理消息=關鍵組件 'Id'不是 類型'Customer'的聲明屬性。確認它沒有明確地從 模型中排除 ,並且它是有效的基元 屬性。來源=的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; } 

} 

謝謝!

回答

2

我不認爲你需要經歷所有這些。 EF 4.1 Code First使用大量的約定而不是配置,通過這種方式,實體的Id屬性被配置爲主鍵。所以通過在你的實體上實現IEntity接口,你可以用Id作爲主鍵來設置它們。

下面是對ADO.NET團隊博客,解釋了主鍵慣例是如何工作的一個環節 - Conventions for Code First

+7

是的,這是真的,但個人而言,我不喜歡依賴這些約定,並且在可能的情況下我想要配置明確,自我記錄和版本控制。遲早會有些東西可能不適合公約,所以這些問題應該可以預先解決。這個簡化示例中還沒有顯示一些共享配置,我不確定該約定是否會自動處理。 – Jamie 2011-04-08 12:17:37

+1

「我不喜歡依賴於約定」 - 然後編寫一個測試,當約定發生變化時它會失敗,記錄事實(用代碼或其他方式)是不太理想的方法 – RhysC 2014-08-22 04:11:43

12

它看起來像這些配置有一些問題與接口。

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() 
    { 
     ... 
    } 
} 
+0

嗯,我試圖轉換接口進入抽象類,它仍然不起作用。然後我讓基類非抽象,它仍然不起作用!我現在已經開始重複配置,直到(有一天?)實體框架團隊支持使用代碼優先(我認爲這是我自己的核心要求)接口的軟件。 – Jamie 2011-04-12 22:23:04

+0

它爲基礎類工作,所以一定有另一個問題。 – 2011-04-12 22:24:02

+0

雖然這對我有用,但我寧願使用界面。 EF希望未來能夠支持這一點。 – jrummell 2011-07-14 13:39:00

1

你可以只創建一個類的靜態方法和實體傳遞到它:如果你改變IEntityEntityBase它的工作原理。例如:

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

不是一個糟糕的解決方法。 – David 2012-08-10 09:15:53

0

我與EF5.0有類似的問題,當我有抽象成員和自定義屬性的Id屬性和實現的通用抽象類。 看起來像實體框架代碼,首先只查看映射的類屬性。 我曾嘗試使用反射器 - 看起來我是對的,但不確定這是100%。

而且,這個幸運的是,已經找到解決方案:

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

所以在我的情況:也映射從基類的屬性我必須添加的代碼m.MapInheritedProperties()一行...