Skip to content

Commit

Permalink
Additional changes related to value generation
Browse files Browse the repository at this point in the history
* Create new page on SQL Server value generation, with information
  on IDENTITY, seed/increment, etc.
* Delete "explicit values for generated properties" page, moving
  relevant content to the new SQL Server page and to the fixed-up
  generated properties page.

Closes #2999
  • Loading branch information
roji committed Jan 13, 2021
1 parent 6eec431 commit 520463c
Show file tree
Hide file tree
Showing 16 changed files with 164 additions and 269 deletions.
5 changes: 5 additions & 0 deletions .openpublishing.redirection.json
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,11 @@
"source_path": "entity-framework/core/miscellaneous/context-pooling.md",
"redirect_url": "/ef/core/performance/advanced-performance-topics#dbcontext-pooling",
"redirect_document_id": false
},
{
"source_path": "core/saving/explicit-values-generated-properties.md",
"redirect_url": "/ef/core/modeling/generated-properties#overriding-values",
"redirect_document_id": false
}
]
}
2 changes: 1 addition & 1 deletion entity-framework/core/change-tracking/explicit-tracking.md
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ Post {Id: 2} Unchanged
This is exactly the same end-state as the previous example that used explicit key values.

> [!TIP]
> An explicit key value can still be set even when using generated key values. EF Core will then attempt to insert using this key value. Some database configurations, including SQL Server with Identity columns, do not support such inserts and will throw.
> An explicit key value can still be set even when using generated key values. EF Core will then attempt to insert using this key value. Some database configurations, including SQL Server with Identity columns, do not support such inserts and will throw ([see these docs for a workaround](xref:core/providers/sql-server/value-generation#inserting-explicit-values-into-identity-columns)).
## Attaching existing entities

Expand Down
15 changes: 11 additions & 4 deletions entity-framework/core/modeling/generated-properties.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ Similarly, a property can be configured to have its value generated on add or up
> Similarly, byte[] properties that are configured as generated on add or update and marked as concurrency tokens are set up with the rowversion data type, so that values are automatically generated in the database. However, specifying `ValueGeneratedOnAddOrUpdate()` will again have no effect.
>
> [!NOTE]
> Depending on the database provider being used, values may be generated client side by EF or in the database. If the value is generated by the database, then EF may assign a temporary value when you add the entity to the context. This temporary value will then be replaced by the database generated value during `SaveChanges()`.
> Depending on the database provider being used, values may be generated client side by EF or in the database. If the value is generated by the database, then EF may assign a temporary value when you add the entity to the context; this temporary value will then be replaced by the database generated value during `SaveChanges()`. For more information, [see the docs on temporary values](xref:core/change-tracking/explicit-tracking#temporary-values).
## Date/time value generation

Expand Down Expand Up @@ -115,11 +115,18 @@ END

For information on creating triggers, [see the documentation on using raw SQL in migrations](xref:core/managing-schemas/migrations/managing#adding-raw-sql).

## Overriding values
## Overriding value generation

If you add an entity to the context that has a value assigned to the property, then EF will attempt to insert that value rather than generating a new one. A property is considered to have a value assigned if it is not assigned the CLR default value (`null` for `string`, `0` for `int`, `Guid.Empty` for `Guid`, etc.).
Although a property is configured for value generation, in many cases you may still explicitly specify a value for it. Whether this will actually work depends on the specific value generation mechanism that has been configured; while you may specify an explicit value instead of using a column's default value, the same cannot be done with computed columns.

For more information, see [Explicit values for generated properties](xref:core/saving/explicit-values-generated-properties).
To override value generation with an explicit value, simply set the property to any value that is not the CLR default value for that property's type (`null` for `string`, `0` for `int`, `Guid.Empty` for `Guid`, etc.).

> [!NOTE]
> Trying to insert explicit values into SQL Server IDENTITY fails by default; [see these docs for a workaround](xref:core/providers/sql-server/value-generation#inserting-explicit-values-into-identity-columns).
To provide an explicit value for properties that have been configured as value generated on add or update, you must also configure the property as follows:

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

## No value generation

Expand Down
2 changes: 1 addition & 1 deletion entity-framework/core/modeling/keys.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ While EF Core supports using properties of any primitive type as the primary key
Key properties must always have a non-default value when adding a new entity to the context, but some types will be [generated by the database](xref:core/modeling/generated-properties). In that case EF will try to generate a temporary value when the entity is added for tracking purposes. After [SaveChanges](/dotnet/api/Microsoft.EntityFrameworkCore.DbContext.SaveChanges) is called the temporary value will be replaced by the value generated by the database.

> [!Important]
> If a key property has its value generated by the database and a non-default value is specified when an entity is added, then EF will assume that the entity already exists in the database and will try to update it instead of inserting a new one. To avoid this turn off value generation or see [how to specify explicit values for generated properties](xref:core/saving/explicit-values-generated-properties).
> If a key property has its value generated by the database and a non-default value is specified when an entity is added, then EF will assume that the entity already exists in the database and will try to update it instead of inserting a new one. To avoid this, turn off value generation or see [how to specify explicit values for generated properties](xref:core/modeling/generated-properties#overriding-value-generation).
## Alternate Keys

Expand Down
38 changes: 38 additions & 0 deletions entity-framework/core/providers/sql-server/value-generation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
title: Microsoft SQL Server Database Provider - Value Generation - EF Core
description: Value Generation Patterns Specific to the SQL Server Entity Framework Core Database Provider
author: roji
ms.date: 1/10/2020
uid: core/providers/sql-server/value-generation
---
# SQL Server Value Generation

This page details value generation configuration and patterns that are specific to the SQL Server provider. It's recommended to first read [the general page on value generation](xref:core/modeling/generated-properties).

## IDENTITY columns

By convention, numeric columns that are configured to have their values generated on add are set up as [SQL Server IDENTITY columns](https://docs.microsoft.com/sql/t-sql/statements/create-table-transact-sql-identity-property).

### Seed and increment

By default, IDENTITY columns start off at 1 (the seed), and increment by 1 each time a row is added (the increment). You can configure a different seed and increment as follows:

[!code-csharp[Main](../../../../samples/core/SqlServer/ValueGeneration/IdentityOptionsContext.cs?name=IdentityOptions&highlight=5)]

> [!NOTE]
> The ability to configure IDENTITY seed and increment was introduced in EF Core 3.0.
### Inserting explicit values into IDENTITY columns

By default, SQL Server doesn't allow inserting explicit values into IDENTITY columns. To do so, you must manually enable `IDENTITY_INSERT` before calling `SaveChanges()`, as follows:

[!code-csharp[Main](../../../../samples/core/SqlServer/ValueGeneration/ExplicitIdentityValues.cs?name=ExplicitIdentityValues)]

> [!NOTE]
> We have a [feature request](https://github.com/aspnet/EntityFramework/issues/703) on our backlog to do this automatically within the SQL Server provider.
## Sequences

As an alternative to IDENTITY columns, you can use standard sequences. This can be useful in various scenarios; for example, you may want to have multiple columns drawing their default values from a single sequence.

SQL Server allows you to create sequences and use them as detailed in [the general page on sequences](xref:core/modeling/sequences). It's up to you to configure your properties to use sequences via `HasDefaultValueSql()`.

This file was deleted.

4 changes: 2 additions & 2 deletions entity-framework/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,6 @@
href: core/saving/transactions.md
- name: Disconnected entities
href: core/saving/disconnected-entities.md
- name: Explicit values for generated properties
href: core/saving/explicit-values-generated-properties.md

- name: Change tracking
items:
Expand Down Expand Up @@ -317,6 +315,8 @@
items:
- name: Overview
href: core/providers/sql-server/index.md
- name: Value generation
href: core/providers/sql-server/value-generation.md
- name: Function mappings
href: core/providers/sql-server/functions.md
- name: Indexes
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Microsoft.EntityFrameworkCore;
using System;
using Microsoft.EntityFrameworkCore.Metadata;

namespace EFModeling.FluentAPI.ValueGeneratedOnAddOrUpdateWithPropertySaveBehavior
{
class MyContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }

#region ValueGeneratedOnAddOrUpdateWithPropertySaveBehavior
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>().Property(b => b.LastUpdated)
.ValueGeneratedOnAddOrUpdate()
.Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Save);
}
#endregion
}

public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
public DateTime LastUpdated { get; set; }
}
}
15 changes: 0 additions & 15 deletions samples/core/Saving/ExplicitValuesGenerateProperties/Employee.cs

This file was deleted.

This file was deleted.

96 changes: 0 additions & 96 deletions samples/core/Saving/ExplicitValuesGenerateProperties/Sample.cs

This file was deleted.

Loading

0 comments on commit 520463c

Please sign in to comment.