Skip to content

Commit

Permalink
Add documentation for pre-convention model configuration
Browse files Browse the repository at this point in the history
Fixes #3278
  • Loading branch information
AndriySvyryd committed Oct 29, 2021
1 parent cef190d commit b84b75b
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 5 deletions.
4 changes: 2 additions & 2 deletions entity-framework/core/cli/powershell.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
72 changes: 72 additions & 0 deletions entity-framework/core/modeling/bulk-configuration.md
Original file line number Diff line number Diff line change
@@ -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 `<navigation property name><principal key property name>` (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 `<principal key property name>`. 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<DateTime>(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<string, object>` 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)
Empty file.
7 changes: 4 additions & 3 deletions entity-framework/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down

0 comments on commit b84b75b

Please sign in to comment.