2017-01-23 5 views
0

まず、継承コードに問題があります。 は、私は次のようになり、基本クラスがあります。EF:流暢なAPIで基本クラスプロパティをマップ

public abstract class BaseEntity 
{ 
    public DateTime? DateCreated { get; set; } 
    public string UserCreatedId { get; set; } 
    public DateTime? DateModified { get; set; } 
    public string UserModifiedId { get; set; } 
    public virtual UserState UserCreated { get; set; } 
    public virtual UserState UserModified { get; set; } 
} 

をし、私はそれを継承し、これが私の名前UserCreated_userStateIdとUserModified_UserStateIdと追加の列を与えています。

modelBuilder.Entity<BaseEntity>().HasOptional(x => x.UserCreated).WithMany().HasForeignKey(x => x.UserCreatedId); 
modelBuilder.Entity<BaseEntity>().HasOptional(X => X.UserModified).WithMany().HasForeignKey(x => x.UserModifiedId); 

しかし、これは私にエラーを与える::だから私はこのような流暢なAPIを試してみてください「は、一つ以上の検証エラーがモデルの生成中に検出されました:

BaseEntity::。EntityType 『BaseEntity』は定義されたキーを持っていない定義このEntityTypeのキー。 BaseEntities:EntityType:EntitySet 'BaseEntities'は、キーが定義されていないタイプ 'BaseEntity'に基づいています。キーの定義を避け、プロパティのマッピングのみを変更する方法私は派生クラスのキーを持っています。

+0

したがって、派生クラスごとに個別のキーを定義し、「コンクリートクラスごとの戦略」戦略を使用する必要がありますか?次に、派生クラスエンティティに対して基本クラスのプロパティを設定する必要があります。 – grek40

+0

私が正しく理解していれば、あなたは** EF継承**を使用していませんが、単純なC#クラスの継承ですか? –

+0

はい、しかし、私はそれをすべて一つずつ構成するためには、多くの派生クラスが必要です。これは私に多くのコピーの貼り付けコードを生成し、私はそれをしたくないです。それ以上の解決策はありますか?はい、私はC#クラスの継承を持っています。私はきれいなモデルを取得し、流暢なAPIのすべてを取得しようとします。 – CrazyBaran

答えて

1

一般的な方法で基本クラス構成をラップし、各具体的なエンティティタイプに対して呼び出すことができます。

static void ConfigureBaseEntity<TDerived>(EntityTypeConfiguration<TDerived> entityTypeConfiguration) where TDerived : BaseEntity 
{ 
    // your base class configuration 
    entityTypeConfiguration.HasOptional(x => x.UserCreated).WithMany().HasForeignKey(x => x.UserCreatedId); 
    entityTypeConfiguration.HasOptional(X => X.UserModified).WithMany().HasForeignKey(x => x.UserModifiedId); 
} 

それぞれの具体的なエンティティタイプのためのコール

public class DerivedEntity : BaseEntity 
{ 
    public int Id { get; set; } 
} 

//... 
ConfigureBaseEntity(modelBuilder.Entity<DerivedEntity>()); 

編集

たぶんTypes構成があなたの目的のために十分です。

modelBuilder.Types<BaseEntity>().Configure(entityTypeConfiguration => /* configure using entityTypeConfiguration */); 

他にも、コメントが反映されている必要があります。たとえば、すべての派生クラスがBaseEntityクラスと同じアセンブリにあり、上記のConfigureBaseEntityメソッドがクラスBaseEntityConfigurationであるとします。

var entityMethod = typeof(DbModelBuilder).GetMethod("Entity"); 
var configurationMethod = typeof(BaseEntityConfiguration).GetMethod("ConfigureBaseEntity"); 
foreach (Type t in typeof(BaseEntity).Assembly.GetTypes().Where(x => x.IsSubclassOf(typeof(BaseEntity)))) 
{ 
    var configurator = entityMethod.MakeGenericMethod(t).Invoke(modelBuilder, new object[0]); 
    configurationMethod.MakeGenericMethod(t).Invoke(null, new object[1] { configurator }); 
} 

しかし、私のコードの場合は、ダイナミックディスカバリーの代わりにエンティティクラスごとに1行のコードを書くことをお勧めします。

+0

多くのDerivedEntityがある場合、この回答は非常に多くのコピー貼り付けコードを生成します、多分それを行うためのいくつかのクリーンな方法ですか? – CrazyBaran

+0

@CrazyBaran派生クラスコレクションを収集し、具体的なクラスごとに1つのライナーが必要な場合は、リフレクションベースのコードを作成するために、リフレクションやMEFのようなものを自由に使用してください。 – grek40

+0

@CrazyBaran私の編集を参照してください、それはあなたが必要とするかもしれません – grek40

関連する問題