Skip to content

Commit

Permalink
Merge default values and computed columns into generated properties
Browse files Browse the repository at this point in the history
Plus some cleanup.

Part of #1669
  • Loading branch information
roji committed Dec 20, 2019
1 parent db44ed6 commit f9adf90
Show file tree
Hide file tree
Showing 14 changed files with 77 additions and 104 deletions.
10 changes: 10 additions & 0 deletions .openpublishing.redirection.json
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,16 @@
"source_path": "entity-framework/core/modeling/relational/sequences.md",
"redirect_url": "/ef/core/modeling/sequences",
"redirect_document_id": false
},
{
"source_path": "entity-framework/core/modeling/relational/default-values.md",
"redirect_url": "/ef/core/modeling/generated-properties#default-values",
"redirect_document_id": false
},
{
"source_path": "entity-framework/core/modeling/relational/computed-columns.md",
"redirect_url": "/ef/core/modeling/generated-properties#computed-columns",
"redirect_document_id": false
}
]
}
75 changes: 50 additions & 25 deletions entity-framework/core/modeling/generated-properties.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ uid: core/modeling/generated-properties

# Generated Values

## Value Generation Patterns
## Value generation patterns

There are three value generation patterns that can be used for properties:

Expand All @@ -29,7 +29,7 @@ Depending on the database provider being used, values may be generated client si

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.). For more information, see [Explicit values for generated properties](../saving/explicit-values-generated-properties.md).

> [!WARNING]
> [!WARNING]
> How the value is generated for added entities will depend on the database provider being used. Database providers may automatically setup value generation for some property types, but others may require you to manually setup how the value is generated.
>
> For example, when using SQL Server, values will be automatically generated for `GUID` properties (using the SQL Server sequential GUID algorithm). However, if you specify that a `DateTime` property is generated on add, then you must setup a way for the values to be generated. One way to do this, is to configure a default value of `GETDATE()`, see [Default Values](relational/default-values.md).
Expand All @@ -47,48 +47,73 @@ Like `value generated on add`, if you specify a value for the property on a newl
>
> [!code-sql[Main](../../../samples/core/Modeling/FluentAPI/ValueGeneratedOnAddOrUpdate.sql)]
## Conventions
## Value generated on add

By convention, non-composite primary keys of type short, int, long, or Guid are set up to have values generated for inserted entities, if a value isn't provided by the application. Your database provider typically takes care of the necessary configuration; for example, a numeric primary key in SQL Server is automatically set up to be an IDENTITY column.

By default, non-composite primary keys of type short, int, long, or Guid will be setup to have values generated on add. All other properties will be setup with no value generation.
You can configure any property to have its value generated for inserted entities as follows:

## Data Annotations
### [Data Annotations](#tab/data-annotations)

### No value generation (Data Annotations)
[!code-csharp[Main](../../../samples/core/Modeling/DataAnnotations/ValueGeneratedOnAdd.cs?name=ValueGeneratedOnAdd&highlight=5)]

[!code-csharp[Main](../../../samples/core/Modeling/DataAnnotations/ValueGeneratedNever.cs#Sample)]
### [Fluent API](#tab/fluent-api)

### Value generated on add (Data Annotations)
[!code-csharp[Main](../../../samples/core/Modeling/FluentAPI/ValueGeneratedOnAdd.cs?name=ValueGeneratedOnAdd&highlight=5)]

[!code-csharp[Main](../../../samples/core/Modeling/DataAnnotations/ValueGeneratedOnAdd.cs#Sample)]
***

> [!WARNING]
> [!WARNING]
> This just lets EF know that values are generated for added entities, it does not guarantee that EF will setup the actual mechanism to generate values. See [Value generated on add](#value-generated-on-add) section for more details.
### Value generated on add or update (Data Annotations)
### Default values

[!code-csharp[Main](../../../samples/core/Modeling/DataAnnotations/ValueGeneratedOnAddOrUpdate.cs#Sample)]
On relational databases, a column can be configured with a default value; if a row is inserted without a value for that column, the default value will be used.

> [!WARNING]
> This just lets EF know that values are generated for added or updated entities, it does not guarantee that EF will setup the actual mechanism to generate values. See [Value generated on add or update](#value-generated-on-add-or-update) section for more details.
You can configure a default value on a property:

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

## Fluent API
You can also specify a SQL fragment that is used to calculate the default value:

You can use the Fluent API to change the value generation pattern for a given property.
[!code-csharp[Main](../../../samples/core/Modeling/FluentAPI/DefaultValueSql.cs?name=DefaultValueSql&highlight=5)]

### No value generation (Fluent API)
Specifying a default value will implicitly configure the property as value generated on add.

[!code-csharp[Main](../../../samples/core/Modeling/FluentAPI/ValueGeneratedNever.cs#Sample)]
## Value generated on add or update

### Value generated on add (Fluent API)
### [Data Annotations](#tab/data-annotations)

[!code-csharp[Main](../../../samples/core/Modeling/FluentAPI/ValueGeneratedOnAdd.cs#Sample)]
[!code-csharp[Main](../../../samples/core/Modeling/DataAnnotations/ValueGeneratedOnAddOrUpdate.cs?name=ValueGeneratedOnAddOrUpdate&highlight=5)]

> [!WARNING]
> `ValueGeneratedOnAdd()` just lets EF know that values are generated for added entities, it does not guarantee that EF will setup the actual mechanism to generate values. See [Value generated on add](#value-generated-on-add) section for more details.
### [Fluent API](#tab/fluent-api)

### Value generated on add or update (Fluent API)
[!code-csharp[Main](../../../samples/core/Modeling/FluentAPI/ValueGeneratedOnAddOrUpdate.cs?name=ValueGeneratedOnAddOrUpdate&highlight=5)]

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

> [!WARNING]
> [!WARNING]
> This just lets EF know that values are generated for added or updated entities, it does not guarantee that EF will setup the actual mechanism to generate values. See [Value generated on add or update](#value-generated-on-add-or-update) section for more details.
### Computed columns

On some relational databases, a column can be configured to have its value computed in the database, typically with an expression referring to other columns:

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

> [!NOTE]
> In some cases the column's value is computed every time it is fetched (sometimes called *virtual* columns), and in others it is computed on every update of the row and stored (sometimes called *stored* or *persisted* columns). This varies across database providers.
## No value generation

Disabling value generation on a property is typically necessary if a convention configures it for value generation. For example, if you have a primary key of type int, it will be implicitly set configured as value generated on add; you can disable this via the following:

### [Data Annotations](#tab/data-annotations)

[!code-csharp[Main](../../../samples/core/Modeling/DataAnnotations/ValueGeneratedNever.cs?name=ValueGeneratedNever&highlight=3)]

### [Fluent API](#tab/fluent-api)

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

***
27 changes: 0 additions & 27 deletions entity-framework/core/modeling/relational/computed-columns.md

This file was deleted.

31 changes: 0 additions & 31 deletions entity-framework/core/modeling/relational/default-values.md

This file was deleted.

4 changes: 0 additions & 4 deletions entity-framework/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,6 @@
items:
- name: Overview
href: core/modeling/relational/index.md
- name: Computed Columns
href: core/modeling/relational/computed-columns.md
- name: Default Values
href: core/modeling/relational/default-values.md
- name: Inheritance (Relational Database)
href: core/modeling/relational/inheritance.md
- name: Managing Database Schemas
Expand Down
4 changes: 2 additions & 2 deletions samples/core/Modeling/DataAnnotations/ValueGeneratedNever.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations.Schema;

namespace EFModeling.DataAnnotations.NoIdentity
namespace EFModeling.DataAnnotations.ValueGeneratedNever
{
class MyContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
}

#region Sample
#region ValueGeneratedNever
public class Blog
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class MyContext : DbContext
public DbSet<Blog> Blogs { get; set; }
}

#region Sample
#region ValueGeneratedOnAdd
public class Blog
{
public int BlogId { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class MyContext : DbContext
public DbSet<Blog> Blogs { get; set; }
}

#region Sample
#region ValueGeneratedOnAddOrUpdate
public class Blog
{
public int BlogId { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@

namespace EFModeling.FluentAPI.Relational.ComputedColumn
{
#region ComputedColumn
class MyContext : DbContext
{
public DbSet<Person> People { get; set; }

#region ComputedColumn
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Person>()
.Property(p => p.DisplayName)
.HasComputedColumnSql("[LastName] + ', ' + [FirstName]");
}
#endregion
}

public class Person
Expand All @@ -22,5 +23,4 @@ public class Person
public string LastName { get; set; }
public string DisplayName { get; set; }
}
#endregion
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@

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

#region DefaultValue
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.Property(b => b.Rating)
.HasDefaultValue(3);
}
#endregion
}

public class Blog
Expand All @@ -21,5 +22,4 @@ public class Blog
public string Url { get; set; }
public int Rating { get; set; }
}
#endregion
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@

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

#region DefaultValueSql
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.Property(b => b.Created)
.HasDefaultValueSql("getdate()");
}
#endregion
}

public class Blog
Expand All @@ -22,5 +23,4 @@ public class Blog
public string Url { get; set; }
public DateTime Created { get; set; }
}
#endregion
}
6 changes: 3 additions & 3 deletions samples/core/Modeling/FluentAPI/ValueGeneratedNever.cs
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
using Microsoft.EntityFrameworkCore;

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

#region ValueGeneratedNever
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
#region Sample
modelBuilder.Entity<Blog>()
.Property(b => b.BlogId)
.ValueGeneratedNever();
#endregion
}
#endregion
}

public class Blog
Expand Down
4 changes: 2 additions & 2 deletions samples/core/Modeling/FluentAPI/ValueGeneratedOnAdd.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ class MyContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }

#region ValueGeneratedOnAdd
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
#region Sample
modelBuilder.Entity<Blog>()
.Property(b => b.Inserted)
.ValueGeneratedOnAdd();
#endregion
}
#endregion
}

public class Blog
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ class MyContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }

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

public class Blog
Expand Down

0 comments on commit f9adf90

Please sign in to comment.