Pola zapasowe

Pola zapasowe umożliwiają programowi EF odczytywanie i/lub zapisywanie w polu, a nie na właściwości. Może to być przydatne, gdy hermetyzacja w klasie jest używana do ograniczania użycia i/lub ulepszania semantyki wokół dostępu do danych za pomocą kodu aplikacji, ale wartość powinna być odczytywana z i/lub zapisywana w bazie danych bez używania tych ograniczeń/ulepszeń.

Konfiguracja podstawowa

Zgodnie z konwencją następujące pola zostaną odnalezione jako pola zapasowe dla danej właściwości (wymienione w kolejności pierwszeństwa).

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

W poniższym przykładzie Url właściwość jest skonfigurowana jako _url pole zapasowe:

public class Blog
{
    private string _url;

    public int BlogId { get; set; }

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

Należy pamiętać, że pola kopii zapasowej są wykrywane tylko dla właściwości uwzględnionych w modelu. Aby uzyskać więcej informacji na temat właściwości uwzględnionych w modelu, zobacz Dołączanie i wykluczanie właściwości.

Pola kopii zapasowej można również skonfigurować przy użyciu adnotacji danych lub interfejsu API Fluent, np. jeśli nazwa pola nie odpowiada powyższym konwencjom:

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;
    }
}

Dostęp do pola i właściwości

Domyślnie program EF zawsze odczytuje i zapisuje w polu zaplecza — zakładając, że został prawidłowo skonfigurowany — i nigdy nie będzie używać właściwości . Jednak program EF obsługuje również inne wzorce dostępu. Na przykład w poniższym przykładzie program EF nakazuje programowi EF zapisywanie w polu zapasowym tylko podczas materializowania i używanie właściwości we wszystkich innych przypadkach:

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

Zobacz wyliczenie PropertyAccessMode, aby uzyskać pełny zestaw obsługiwanych opcji.

Właściwości tylko pola

Można również utworzyć właściwość koncepcyjną w modelu, która nie ma odpowiedniej właściwości CLR w klasie jednostek, ale zamiast tego używa pola do przechowywania danych w jednostce. Różni się to od właściwości cienia, gdzie dane są przechowywane w monitorze zmian, a nie w typie CLR jednostki. Właściwości tylko dla pól są często używane, gdy klasa jednostki używa metod zamiast właściwości do pobierania/ustawiania wartości lub w przypadkach, gdy pola nie powinny być uwidocznione w ogóle w modelu domeny (np. klucze podstawowe).

Właściwość tylko dla pola można skonfigurować, podając nazwę w interfejsie 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;
    }
}

Program EF podejmie próbę znalezienia właściwości CLR o podanej nazwie lub polu, jeśli właściwość nie zostanie znaleziona. Jeśli nie zostanie znaleziona żadna właściwość ani pole, zamiast tego zostanie skonfigurowana właściwość w tle.

Może być konieczne odwołanie się do właściwości tylko dla pola z zapytań LINQ, ale takie pola są zwykle prywatne. Możesz użyć EF.Property(...) metody w zapytaniu LINQ, aby odwołać się do pola:

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