次の方法で共有


バッキング フィールド

バッキング フィールドを使用すると、EF はプロパティではなくフィールドの読み取りや書き込みを行います。 これは、クラス内のカプセル化を使用して、アプリケーション コードによるデータへのアクセスに関するセマンティクスの制限や強化を行うときに役立ちますが、これらの制限/機能強化を使用せずに、値をデータベースから読み取ったり、データベースに書き込んだりする必要があります。

基本的な構成

規則により、次のフィールドは、特定のプロパティのバッキング フィールドとして検出されます (優先順位で一覧表示されます)。

  • <camel-cased property name>
  • _<camel-cased property name>
  • _<property name>
  • m_<camel-cased property name>
  • m_<property name>

次の例では、 Url プロパティがバッキング フィールドとして _url するように構成されています。

public class Blog
{
    private string _url;

    public int BlogId { get; set; }

    public string Url
    {
        get { return _url; }
        set { _url = value; }
    }
}

バッキング フィールドは、モデルに含まれるプロパティに対してのみ検出されることに注意してください。 モデルに含めるプロパティの詳細については、「プロパティの 追加と除外」を参照してください。

フィールド名が上記の規則に対応していない場合など、 データ注釈 または Fluent API を使用してバッキング フィールドを構成することもできます。

public class Blog
{
    private string _validatedUrl;

    public int BlogId { get; set; }

    [BackingField(nameof(_validatedUrl))]
    public string Url
    {
        get { return _validatedUrl; }
    }

    public void SetUrl(string url)
    {
        // put your validation code here

        _validatedUrl = url;
    }
}

フィールドとプロパティのアクセス

既定では、EF は常にバッキング フィールドの読み取りと書き込みを行います 。正しく構成されていると仮定すると、このプロパティは使用されません。 ただし、EF は他のアクセス パターンもサポートしています。 たとえば、次の例では、具体化中にのみバッキング フィールドに書き込み、他のすべての場合にプロパティを使用するように EF に指示します。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .Property(b => b.Url)
        .HasField("_validatedUrl")
        .UsePropertyAccessMode(PropertyAccessMode.PreferFieldDuringConstruction);
}

サポートされているオプションの完全なセットについては、 PropertyAccessMode 列挙型 を参照してください。

フィールドのみのプロパティ

また、エンティティ クラスに対応する CLR プロパティを持たない概念プロパティをモデルに作成することもできますが、代わりにフィールドを使用してエンティティにデータを格納します。 これは、エンティティの CLR 型ではなく、変更トラッカーにデータが格納される シャドウ プロパティとは異なります。 フィールドのみのプロパティは、エンティティ クラスがプロパティの代わりにメソッドを使用して値を取得または設定する場合、またはドメイン モデルでフィールドをまったく公開しない場合 (主キーなど) に一般的に使用されます。

Property(...) API で名前を指定することで、フィールドのみのプロパティを構成できます。

internal class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
            .Property("_validatedUrl");
    }
}

public class Blog
{
    private string _validatedUrl;

    public int BlogId { get; set; }

    public string GetUrl()
    {
        return _validatedUrl;
    }

    public void SetUrl(string url)
    {
        using (var client = new HttpClient())
        {
            var response = client.GetAsync(url).Result;
            response.EnsureSuccessStatusCode();
        }

        _validatedUrl = url;
    }
}

EF は、指定された名前の CLR プロパティ、またはプロパティが見つからない場合はフィールドの検索を試みます。 プロパティもフィールドも見つからない場合は、代わりにシャドウ プロパティが設定されます。

LINQ クエリからフィールドのみのプロパティを参照する必要がある場合がありますが、通常、このようなフィールドはプライベートです。 LINQ クエリで EF.Property(...) メソッドを使用して、フィールドを参照できます。

var blogs = db.blogs.OrderBy(b => EF.Property<string>(b, "_validatedUrl"));