Skip to content

Commit

Permalink
Improve backing field modeling page
Browse files Browse the repository at this point in the history
* Reorganize content based on topics and not convention/fluent API/data annotations, as done in #1669.
* Correct the documentation of the default property access mode (change from PreferFieldDuringConstruction to PreferField in 3.0), and add a note on the behavior change.
* Various other cleanups and improvements.
  • Loading branch information
roji committed Dec 20, 2019
1 parent a62fb8e commit 6c97f2f
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 24 deletions.
38 changes: 19 additions & 19 deletions entity-framework/core/modeling/backing-field.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,49 +7,49 @@ uid: core/modeling/backing-field
---
# Backing Fields

> [!NOTE]
> This feature is new in EF Core 1.1.
Backing fields allow EF to read and/or write to a field rather than a property. This can be useful when encapsulation in the class is being used to restrict the use of and/or enhance the semantics around access to the data by application code, but the value should be read from and/or written to the database without using those restrictions/enhancements.

## Conventions
## Basic configuration

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](included-properties.md).
By convention, the following fields will be discovered as backing fields for a given property (listed in precedence order).

* `_<camel-cased property name>`
* `_<property name>`
* `m_<camel-cased property name>`
* `m_<property name>`

[!code-csharp[Main](../../../samples/core/Modeling/Conventions/BackingField.cs#Sample)]
In the following sample, the `Url` property is configured to have `_url` as its backing field:

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.
[!code-csharp[Main](../../../samples/core/Modeling/Conventions/BackingField.cs#Sample)]

## Data Annotations
Note that backing 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](included-properties.md).

Backing fields cannot be configured with data annotations.
You can also configure backing fields explicitly, e.g. if the field name doesn't correspond to the above conventions:

## Fluent API
[!code-csharp[Main](../../../samples/core/Modeling/FluentAPI/BackingField.cs?name=BackingField&highlight=5)]

You can use the Fluent API to configure a backing field for a property.
## Field and property access

[!code-csharp[Main](../../../samples/core/Modeling/FluentAPI/BackingField.cs#Sample)]
By default, EF will always read and write to the backing field - assuming one has been properly configured - and will never use the property. However, EF also supports other access patterns. For example, the following sample instructs EF to write to the backing field only while materializing, and to use the property in all other cases:

### Controlling when the field is used
[!code-csharp[Main](../../../samples/core/Modeling/FluentAPI/BackingFieldAccessMode.cs?name=BackingFieldAccessMode&highlight=6)]

You can configure when EF uses the field or property. See the [PropertyAccessMode enum](https://docs.microsoft.com/dotnet/api/microsoft.entityframeworkcore.propertyaccessmode) for the supported options.
See the [PropertyAccessMode enum](https://docs.microsoft.com/dotnet/api/microsoft.entityframeworkcore.propertyaccessmode) for the complete set of supported options.

[!code-csharp[Main](../../../samples/core/Modeling/FluentAPI/BackingFieldAccessMode.cs#Sample)]
> [!NOTE]
> With EF Core 3.0, the default property access mode changed from `PreferFieldDuringConstruction` to `PreferField`.
### Fields without a property
## Field-only properties

You can also create a conceptual property in your model that does not have a corresponding CLR property in the entity class, but instead uses a field to store the data in the entity. This is different from [Shadow Properties](shadow-properties.md), 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 also create a conceptual property in your model that does not have a corresponding CLR property in the entity class, but instead uses a field to store the data in the entity. This is different from [Shadow Properties](shadow-properties.md), where the data is stored in the change tracker, rather than in the entity's CLR type. Field-only properties are typically used when the entity class uses methods to get/set values, instead of properties.

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.
You can configure a field-only property by providing a name in the `Property(...)` API:

[!code-csharp[Main](../../../samples/core/Modeling/FluentAPI/BackingFieldNoProperty.cs#Sample)]

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.
EF will attempt to find a CLR property with the given name, or a field if a property isn't found. If neither a property nor a field are found, a shadow property will be set up instead.

You may need to refer to a field-only property from LINQ queries, but such fields are typically private. You can use the `EF.Property(...)` method in a LINQ query to refer to the field:

``` csharp
var blogs = db.blogs.OrderBy(b => EF.Property<string>(b, "_validatedUrl"));
Expand Down
4 changes: 2 additions & 2 deletions samples/core/Modeling/FluentAPI/BackingField.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@

namespace EFModeling.FluentAPI.BackingField
{
#region Sample
class MyContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }

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

public class Blog
Expand All @@ -38,5 +39,4 @@ public void SetUrl(string url)
_validatedUrl = url;
}
}
#endregion
}
6 changes: 3 additions & 3 deletions samples/core/Modeling/FluentAPI/BackingFieldAccessMode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ class MyContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }

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

public class Blog
Expand Down

0 comments on commit 6c97f2f

Please sign in to comment.