0

はこのような何かをすることが可能です:EFコアベースのエンティティクラスの継承と読み取り専用のプロパティ

public abstract class BaseEntity : IEntity 
{ 
    private Guid _id; 
    private DateTime _createdOn; 
    private DateTime _modifiedOn; 
    private byte[] _timestamp; 

    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public Guid Id => _id; 

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public DateTime CreatedOn => _createdOn; 

    [DatabaseGenerated(DatabaseGeneratedOption.Computed)] 
    public DateTime ModifiedOn => _modifiedOn; 

    [Timestamp] 
    public byte[] Timestamp => _timestamp; 
} 

これは、基本クラスで、すべてのエンティティは、このクラスから継承する必要があります。また、このプロパティはreadonly(私はbacking propertiesを使用しています)である必要があります。なぜなら、EFはそれらを処理する必要があるからです。

public class Category : BaseEntity 
{ 
    [Required] 
    public string Name { get; set; } 

    public string Description { get; set; } 
} 

OnModelCreatingは空です。 私はマイグレーションを実行すると、私はメッセージを取得:

「エンティティタイプは 『Project.Database.Models.Category』が定義されるように、主 キーが必要です。

答えて

2

問題は、BaseEntity.Idプロパティが読み取り専用であることです。

あなたのIdプロパティは、expression-bodied member(=>構文)として実装されています。これは、get-onlyプロパティの文法的な砂糖です。

だから、あなたのコード:

public Guid Id => _id; 

は同等です:

public Guid Id { get { return _id; } } 

EFがマッピングされたプロパティの値を設定することができなければなりません。プロパティを実装するには従来の構文を使用する必要があり、セッターを用意する必要があります。コンテキストがモデルと同じアセンブリ内にある場合は、セッターを内部としてマークして、プロパティがアセンブリの外部でのみ読み取られるようにすることができます。コンテキストが別のアセンブリにある場合でも、セッターを内部としてマークしてから、InternalsVisibleTo属性を使用して、コンテキストを含むアセンブリに内部を表示させることができます。

+1

これはバッキングフィールドで処理しないでください。次に、バッキングフィールドを使用する必要がありますか? –

+0

バッキングフィールドは_idであり、どちらのメソッド実装でも使用されています。ただし、バッキングフィールドはデータベース列にマップされているものではありません。プロパティはです。バッキングフィールドは、Entity Framework(および他のすべてのもの)が何も知らない/気にすることのないモデルクラス内のプライベートなメカニズムです。 – Pat

+1

オブジェクトが作成されるとバッキングフィールドが設定され、プロパティはEFがデータベースにマップするものです。なぜこれがうまくいかないのかまだ分かりません。 "バッキングフィールドが設定されている場合、EFはプロパティセッターを使用するのではなく、データベースのエンティティインスタンスをマテリアライズするときに、そのフィールドに直接書き込みます。データベースからロードされる既存のエンティティの初期プロパティ値を設定するときに実行されます。" - ef core docs –

2

これは、あなたがpublicinternalまたはprotected(ただしprivateまたはnone)Idプロパティのセッターを、提供する場合、それが動作するため、バグのようですか、あなたはのキーを指定した場合流暢経由エンティティ明示的に導出しましたAPI

modelBuilder.Entity<Category>().HasKey(e => e.Id); 

もちろん、基本クラスプロパティを使用する目的はすべて無効です。

EFコアGitHubに報告するとよいかもしれません。

+0

これはバグではありません。 OPのコードでは、このプロパティにはセッターがありません。それはうまくいかないでしょう。 – Pat

+1

@Patそれでは、それがなぜ他のケースで動作するのですか? –

関連する問題