Campos de respaldo

Los campos de respaldo permiten a EF leer o escribir en un campo en lugar de una propiedad. Esto puede ser útil cuando se usa la encapsulación en la clase para restringir el uso de y/o mejorar la semántica en torno al acceso a los datos por código de aplicación, pero el valor debe leerse o escribirse en la base de datos sin usar esas restricciones o mejoras.

Configuración básica

Por convención, los campos siguientes se detectarán como campos de respaldo para una propiedad determinada (enumerada en orden de precedencia).

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

En el ejemplo siguiente, la propiedad Url está configurada para tener _url como campo de respaldo:

public class Blog
{
    private string _url;

    public int BlogId { get; set; }

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

Tenga en cuenta que los campos de respaldo solo se detectan para las propiedades que se incluyen en el modelo. Para obtener más información sobre qué propiedades se incluyen en el modelo, vea Inclusión y exclusión de propiedades.

También puede configurar campos de respaldo mediante las Anotaciones de datos o la API de Fluent, por ejemplo, si el nombre del campo no se corresponde con las convenciones anteriores:

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

Acceso a campos y propiedades

De forma predeterminada, EF siempre leerá y escribirá en el campo de respaldo (suponiendo que se haya configurado correctamente) y nunca usará la propiedad. Sin embargo, EF también admite otros patrones de acceso. Por ejemplo, en el ejemplo siguiente se indica a EF que escriba en el campo de respaldo solo mientras se materializa y que use la propiedad en todos los demás casos:

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

Consulte la enumeración PropertyAccessMode para obtener el conjunto completo de opciones admitidas.

Propiedades de solo campo

También puede crear una propiedad conceptual en el modelo que no tenga una propiedad CLR correspondiente en la clase de entidad, sino que use un campo para almacenar los datos en la entidad. Esto es diferente de las propiedades de sombra, donde los datos se almacenan en el seguimiento de cambios, en lugar de en el tipo CLR de la entidad. Las propiedades de solo campo se usan normalmente cuando la clase de la entidad usa métodos en lugar de propiedades para obtener o establecer valores, o en los casos en los que los campos no deben exponerse en absoluto en el modelo de dominio (por ejemplo, claves principales).

Puede configurar una propiedad solo de campo proporcionando un nombre en la API de 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 intentará buscar una propiedad CLR con el nombre especificado o un campo si no se encuentra una propiedad. Si no se encuentra ninguna propiedad ni un campo, se configurará una propiedad reemplazada en su lugar.

Es posible que tenga que hacer referencia a una propiedad de solo campo de las consultas LINQ, aunque estos campos suelen ser privados. Puede usar el método EF.Property(...) en una consulta LINQ para hacer referencia al campo:

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