Backing Fields

Note

This documentation is for EF Core. For EF6.x, see Entity Framework 6.

Backing fields allow EF to read and/or write to a field rather than a property.

Note

Backing Field support was introduced in EF Core 1.1.0. If you are using an earlier release, the functionality shown in this article will not be available.

Conventions

By convention, the following fields will be discovered as backing fields for a given property (listed in precedence order). Fields are only discovered for properties that are included in the model. For more information on which properties are included in the model, see Including & Excluding Properties.

  • _<camel-cased property name>
  • _<property name>
  • m_<camel-cased property name>
  • m_<property name>
public class Blog
{
    private string _url;

    public int BlogId { get; set; }

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

When a backing field is configured, EF will write directly to that field when materializing entity instances from the database (rather than using the property setter). If EF needs to read or write the value at other times, it will use the property if possible. For example, if EF needs to update the value for a property, it will use the property setter if one is defined. If the property is read-only, then it will write to the field.

Data Annotations

Backing fields cannot be configured with data annotations.

Fluent API

You can use the Fluent API to configure a backing field for a property.

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

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

public class Blog
{
    private string _validatedUrl;

    public int BlogId { get; set; }

    public string Url
    {
        get { return _validatedUrl; }
    }

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

        _validatedUrl = url;
    }
}

Controlling when the field is used

You can configure when EF uses the field or property. See the PropertyAccessMode enum for the supported options.

modelBuilder.Entity<Blog>()
    .Property(b => b.Url)
    .HasField("_validatedUrl")
    .UsePropertyAccessMode(PropertyAccessMode.Field);

Fields without a property

You can also create a property in your model that does not have a corresponding property in the entity class, but uses a field to store the data in the entity. This is different from Shadow Properties, where the data is stored in the change tracker. This would typically be used if the entity class uses methods to get/set values.

You can give EF the name of the field in the Property(...) API. If there is no property with the given name, then EF will look for a field.

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

You can also choose to give the property a name, other than the field name. This name is then used when creating the model, most notably it will be used for the column name that is mapped to in the database.

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

When there is no property in the entity class, you can use the EF.Property(...) method in a LINQ query to refer to the property that is conceptually part of the model.

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