From b84b75bc6a19870d0632c2c3d3f62993fd354c57 Mon Sep 17 00:00:00 2001 From: Andriy Svyryd Date: Fri, 29 Oct 2021 10:22:37 -0700 Subject: [PATCH] Add documentation for pre-convention model configuration Fixes #3278 --- entity-framework/core/cli/powershell.md | 4 +- .../core/modeling/bulk-configuration.md | 72 +++++++++++++++++++ .../core/modeling/conventions.md.stub | 0 entity-framework/toc.yml | 7 +- 4 files changed, 78 insertions(+), 5 deletions(-) create mode 100644 entity-framework/core/modeling/bulk-configuration.md delete mode 100644 entity-framework/core/modeling/conventions.md.stub diff --git a/entity-framework/core/cli/powershell.md b/entity-framework/core/cli/powershell.md index 9e50b1fd47..6f216b067b 100644 --- a/entity-framework/core/cli/powershell.md +++ b/entity-framework/core/cli/powershell.md @@ -224,13 +224,13 @@ Parameters: The [common parameters](#common-parameters) are listed above. -Example that uses the defaults and works if there is only one `DbContext` in the project: +The following example uses the defaults and works if there is only one `DbContext` in the project: ```powershell Optimize-DbContext ``` -Example that optimizes the model for the context with the specified name amd places it in a separate folder and namespace: +The following example optimizes the model for the context with the specified name and places it in a separate folder and namespace: ```powershell Optimize-DbContext -OutputDir Models -Namespace BlogModels -Context BlogContext diff --git a/entity-framework/core/modeling/bulk-configuration.md b/entity-framework/core/modeling/bulk-configuration.md new file mode 100644 index 0000000000..45b62ad146 --- /dev/null +++ b/entity-framework/core/modeling/bulk-configuration.md @@ -0,0 +1,72 @@ +--- +title: Model Bulk Configuration - EF Core +description: How to apply bulk configuration during model building in Entity Framework Core +author: AndriySvyryd +ms.date: 10/25/2021 +uid: core/modeling/bulk-configuration +--- +# Model bulk configuration + +When an aspect needs to be configured in the same way across multiple entity types the following techniques allow to reduce code duplication and consolidate the logic. + +## Foreign key shadow properties + +Shadow properties are most often used for foreign key properties, where the relationship between two entities is represented by a foreign key value in the database, but the relationship is managed on the entity types using navigation properties between the entity types. By convention, EF will introduce a shadow property when a relationship is discovered but no foreign key property is found in the dependent entity class. + +The property will be named `` (the navigation on the dependent entity, which points to the principal entity, is used for the naming). If the principal key property name includes the name of the navigation property, then the name will just be ``. If there is no navigation property on the dependent entity, then the principal type name is used in its place. + +For example, the following code listing will result in a `BlogId` shadow property being introduced to the `Post` entity: + +[!code-csharp[Main](../../../samples/core/Modeling/ShadowAndIndexerProperties/ShadowForeignKey.cs?name=Conventions&highlight=21-23)] + +## Configuring shadow properties + +You can use the Fluent API to configure shadow properties. Once you have called the string overload of `Property`, you can chain any of the configuration calls you would for other properties. In the following sample, since `Blog` has no CLR property named `LastUpdated`, a shadow property is created: + +[!code-csharp[Main](../../../samples/core/Modeling/ShadowAndIndexerProperties/ShadowProperty.cs?name=ShadowProperty&highlight=8)] + +If the name supplied to the `Property` method matches the name of an existing property (a shadow property or one defined on the entity class), then the code will configure that existing property rather than introducing a new shadow property. + +## Accessing shadow properties + +Shadow property values can be obtained and changed through the `ChangeTracker` API: + +```csharp +context.Entry(myBlog).Property("LastUpdated").CurrentValue = DateTime.Now; +``` + +Shadow properties can be referenced in LINQ queries via the `EF.Property` static method: + +```csharp +var blogs = context.Blogs + .OrderBy(b => EF.Property(b, "LastUpdated")); +``` + +Shadow properties cannot be accessed after a no-tracking query since the entities returned are not tracked by the change tracker. + +## Configuring indexer properties + +You can use the Fluent API to configure indexer properties. Once you've called the method `IndexerProperty`, you can chain any of the configuration calls you would for other properties. In the following sample, `Blog` has an indexer defined and it will be used to create an indexer property. + +[!code-csharp[Main](../../../samples/core/Modeling/ShadowAndIndexerProperties/IndexerProperty.cs?name=IndexerProperty&highlight=7)] + +If the name supplied to the `IndexerProperty` method matches the name of an existing indexer property, then the code will configure that existing property. If the entity type has a property, which is backed by a property on the entity class, then an exception is thrown since indexer properties must only be accessed via the indexer. + +Indexer properties can be referenced in LINQ queries via the `EF.Property` static method as shown above or by using the CLR indexer property. + +## Property bag entity types + +> [!NOTE] +> Support for Property bag entity types was introduced in EF Core 5.0. + +Entity types that contain only indexer properties are known as property bag entity types. These entity types don't have shadow properties, and EF creates indexer properties instead. Currently only `Dictionary` is supported as a property bag entity type. It must be configured as a [shared-type entity type](entity-types.md#shared-type-entity-types) with a unique name and the corresponding `DbSet` property must be implemented using a `Set` call. + +[!code-csharp[Main](../../../samples/core/Modeling/ShadowAndIndexerProperties/SharedType.cs?name=SharedType&highlight=3,7)] + +Property bag entity types can be used wherever a normal entity type is used, including as an owned entity type. However, they do have certain limitations: + +- They can't have shadow properties. +- [Indexer navigations aren't supported](https://github.com/dotnet/efcore/issues/13729) +- [Inheritance isn't supported](https://github.com/dotnet/efcore/issues/9630) +- [Some relationship model-building API lack overloads for shared-type entity types](https://github.com/dotnet/efcore/issues/23255) +- [Other types can't be marked as property bags](https://github.com/dotnet/efcore/issues/22009) diff --git a/entity-framework/core/modeling/conventions.md.stub b/entity-framework/core/modeling/conventions.md.stub deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/entity-framework/toc.yml b/entity-framework/toc.yml index 42d4e16d28..07ddc021b9 100644 --- a/entity-framework/toc.yml +++ b/entity-framework/toc.yml @@ -137,12 +137,13 @@ href: core/modeling/owned-entities.md - name: Keyless entity types href: core/modeling/keyless-entity-types.md - - name: Alternating models with same DbContext - href: core/modeling/dynamic-model.md - name: Spatial data displayName: GIS href: core/modeling/spatial.md - #- name: Conventions + - name: Bulk configuration + href: core/modeling/bulk-configuration.md + - name: Alternating models with same DbContext + href: core/modeling/dynamic-model.md - name: Manage database schemas items: