Share via


支援欄位

備份欄位允許 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 類型中。 當實體類別使用方法而非屬性來取得/設定值時,通常會使用僅限欄位的屬性,或在領域模型中完全不應該公開字段的情況(例如主鍵)。

您可以在 API 中 Property(...) 提供名稱來設定只限欄位的屬性:

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"));