Skip to content

Commit

Permalink
Merge primary-key and alternative-keys into keys page
Browse files Browse the repository at this point in the history
Part of #1669
Fixes #862
  • Loading branch information
roji committed Dec 11, 2019
1 parent a94eed5 commit 68e45d3
Show file tree
Hide file tree
Showing 14 changed files with 72 additions and 114 deletions.
10 changes: 10 additions & 0 deletions .openpublishing.redirection.json
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,16 @@
"source_path": "entity-framework/core/modeling/relational/default-schema.md",
"redirect_url": "/ef/core/modeling/entity-types",
"redirect_document_id": false
},
{
"source_path": "entity-framework/core/modeling/alternate-keys.md",
"redirect_url": "/ef/core/modeling/keys#alternate-keys",
"redirect_document_id": false
},
{
"source_path": "entity-framework/core/modeling/relational/primary-keys.md",
"redirect_url": "/ef/core/modeling/keys",
"redirect_document_id": false
}
]
}
35 changes: 0 additions & 35 deletions entity-framework/core/modeling/alternate-keys.md

This file was deleted.

59 changes: 39 additions & 20 deletions entity-framework/core/modeling/keys.md
Original file line number Diff line number Diff line change
@@ -1,49 +1,68 @@
---
title: Keys (primary) - EF Core
title: Keys - EF Core
description: How to configure keys for entity types when using Entity Framework Core
author: AndriySvyryd
ms.author: ansvyryd
ms.date: 11/06/2019
uid: core/modeling/keys
---
# Keys (primary)
# Keys

A key serves as the primary unique identifier for each entity instance. When using a relational database this maps to the concept of a *primary key*. You can also configure a unique identifier that is not the primary key (see [Alternate Keys](alternate-keys.md) for more information).
A key serves as a unique identifier for each entity instance. Most entities in EF have a single key, which maps to the concept of a *primary key* in relational databases (for entities without a primary, see [Keyless entities](xref:core/modeling/keyless-entity-types)). Entities can have additional keys beyond the primary key (see [Alternate Keys](#alternate-keys) for more information).

One of the following methods can be used to setup/create a primary key.
By convention, a property named `Id` or `<type name>Id` will be configured as the primary key of an entity.

## Conventions
[!code-csharp[Main](../../../samples/core/Modeling/Conventions/KeyId.cs?name=KeyId&highlight=3,11)]

By default, a property named `Id` or `<type name>Id` will be configured as the key of an entity.
> [!NOTE]
> [Owned entity types](xref:core/modeling/owned-entities) use different rules to define keys.
[!code-csharp[Main](../../../samples/core/Modeling/Conventions/KeyId.cs?name=KeyId&highlight=3)]
You can configure a single property to be the primary key of an entity as follows:

[!code-csharp[Main](../../../samples/core/Modeling/Conventions/KeyTypeNameId.cs?name=KeyId&highlight=3)]
## [Data Annotations](#tab/data-annotations)

> [!NOTE]
> [Owned entity types](xref:core/modeling/owned-entities) use different rules to define keys.
[!code-csharp[Main](../../../samples/core/Modeling/DataAnnotations/KeySingle.cs?name=KeySingle&highlight=3)]

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

You can use Data Annotations to configure a single property to be the key of an entity.
[!code-csharp[Main](../../../samples/core/Modeling/FluentAPI/KeySingle.cs?name=KeySingle&highlight=3-4)]

[!code-csharp[Main](../../../samples/core/Modeling/DataAnnotations/KeySingle.cs?highlight=13)]
***

## Fluent API
You can also configure multiple properties to be the key of an entity - this is known as a composite key. Composite keys can only be configured using the Fluent API; conventions will never setup a composite key, and you can not use Data Annotations to configure one.

You can use the Fluent API to configure a single property to be the key of an entity.
[!code-csharp[Main](../../../samples/core/Modeling/FluentAPI/KeyComposite.cs?name=KeyComposite&highlight=4)]

[!code-csharp[Main](../../../samples/core/Modeling/FluentAPI/KeySingle.cs?highlight=11,12)]
## Primary key name

You can also use the Fluent API to configure multiple properties to be the key of an entity (known as a composite key). Composite keys can only be configured using the Fluent API - conventions will never setup a composite key and you can not use Data Annotations to configure one.
By convention, on relational databases primary keys are created with the name `PK_<type name>`. You can use the Fluent API to configure the name of the primary key constraint as follows:

[!code-csharp[Main](../../../samples/core/Modeling/FluentAPI/KeyComposite.cs?highlight=11,12)]
[!code-csharp[Main](../../../samples/core/Modeling/FluentAPI/KeyName.cs?name=KeyName&highlight=5)]

## Key types and values

EF Core supports using properties of any primitive type as the primary key, including `string`, `Guid`, `byte[]` and others. But not all databases support them. In some cases the key values can be converted to a supported type automatically, otherwise the conversion should be [specified manually](xref:core/modeling/value-conversions).
While EF Core supports using properties of any primitive type as the primary key, including `string`, `Guid`, `byte[]` and others, not all databases support all types as keys. In some cases the key values can be converted to a supported type automatically, otherwise the conversion should be [specified manually](xref:core/modeling/value-conversions).

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 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](../saving/explicit-values-generated-properties.md).
> 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](../saving/explicit-values-generated-properties.md).
## Alternate Keys

An alternate key serves as an alternate unique identifier for each entity instance in addition to the primary key; it can be used as the target of a relationship. When using a relational database this maps to the concept of a unique index/constraint on the alternate key column(s) and one or more foreign key constraints that reference the column(s).

> [!TIP]
> If you just want to enforce uniqueness on a column, define a unique index rather than an alternate key (see [Indexes](indexes.md)). In EF, alternate keys provide additional semantics over unique indexes because they can be used as the target of a foreign key.
Alternate keys are typically introduced for you when needed and you do not need to manually configure them. By convention, an alternate key is introduced for you when you identify a property which isn't the primary key as the target of a relationship.

[!code-csharp[Main](../../../samples/core/Modeling/Conventions/AlternateKey.cs?name=AlternateKey&highlight=12)]

You can also use the Fluent API to configure a single property to be an alternate key:

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

You can also use the Fluent API to configure multiple properties to be an alternate key (known as a composite alternate key):

[!code-csharp[Main](../../../samples/core/Modeling/FluentAPI/AlternateKeyComposite.cs?name=AlternateKeyComposite&highlight=4)]
27 changes: 0 additions & 27 deletions entity-framework/core/modeling/relational/primary-keys.md

This file was deleted.

2 changes: 1 addition & 1 deletion entity-framework/efcore-and-ef6/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ EF Core was designed to provide a developer experience similar to EF6. Most of t

## Feature comparison

EF Core offers new features that won't be implemented in EF6 (such as [alternate keys](xref:core/modeling/alternate-keys), [batch updates](xref:core/what-is-new/ef-core-1.0#relational-batching-of-statements), and [mixed client/database evaluation in LINQ queries](xref:core/querying/client-eval). But because it's a new code base, it also lacks some features that EF6 has.
EF Core offers new features that won't be implemented in EF6 (such as [alternate keys](xref:core/modeling/keys#alternate-keys), [batch updates](xref:core/what-is-new/ef-core-1.0#relational-batching-of-statements), and [mixed client/database evaluation in LINQ queries](xref:core/querying/client-eval). But because it's a new code base, it also lacks some features that EF6 has.

The following tables compare the features available in EF Core and EF6. It's a high-level comparison and doesn't list every feature or explain differences between the same feature in different EF versions.

Expand Down
6 changes: 1 addition & 5 deletions entity-framework/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
href: core/modeling/entity-types.md
- name: "Including & Excluding Properties"
href: core/modeling/included-properties.md
- name: Keys (primary)
- name: Keys
href: core/modeling/keys.md
- name: Generated Values
href: core/modeling/generated-properties.md
Expand All @@ -99,8 +99,6 @@
href: core/modeling/relationships.md
- name: Indexes
href: core/modeling/indexes.md
- name: Alternate Keys
href: core/modeling/alternate-keys.md
- name: Inheritance
href: core/modeling/inheritance.md
- name: Backing Fields
Expand Down Expand Up @@ -129,8 +127,6 @@
href: core/modeling/relational/columns.md
- name: Data Types
href: core/modeling/relational/data-types.md
- name: Primary Keys
href: core/modeling/relational/primary-keys.md
- name: Computed Columns
href: core/modeling/relational/computed-columns.md
- name: Sequences
Expand Down
9 changes: 9 additions & 0 deletions samples/core/Modeling/Conventions/KeyId.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace EFModeling.Conventions.KeyId
class MyContext : DbContext
{
public DbSet<Car> Cars { get; set; }
public DbSet<Truck> Trucks { get; set; }
}

#region KeyId
Expand All @@ -16,5 +17,13 @@ class Car
public string Make { get; set; }
public string Model { get; set; }
}

class Truck
{
public string TruckId { get; set; }

public string Make { get; set; }
public string Model { get; set; }
}
#endregion
}
20 changes: 0 additions & 20 deletions samples/core/Modeling/Conventions/KeyTypeNameId.cs

This file was deleted.

2 changes: 2 additions & 0 deletions samples/core/Modeling/DataAnnotations/KeySingle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class MyContext : DbContext
public DbSet<Car> Cars { get; set; }
}

#region KeySingle
class Car
{
[Key]
Expand All @@ -16,4 +17,5 @@ class Car
public string Make { get; set; }
public string Model { get; set; }
}
#endregion
}
4 changes: 2 additions & 2 deletions samples/core/Modeling/FluentAPI/AlternateKeyComposite.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@

namespace EFModeling.FluentAPI.AlternateKeyComposite
{
#region AlternateKeyComposite
class MyContext : DbContext
{
public DbSet<Car> Cars { get; set; }

#region AlternateKeyComposite
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Car>()
.HasAlternateKey(c => new { c.State, c.LicensePlate });
}
#endregion
}

class Car
Expand All @@ -22,5 +23,4 @@ class Car
public string Make { get; set; }
public string Model { get; set; }
}
#endregion
}
4 changes: 2 additions & 2 deletions samples/core/Modeling/FluentAPI/AlternateKeySingle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@

namespace EFModeling.FluentAPI.AlternateKeySingle
{
#region AlternateKeySingle
class MyContext : DbContext
{
public DbSet<Car> Cars { get; set; }

#region AlternateKeySingle
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Car>()
.HasAlternateKey(c => c.LicensePlate);
}
#endregion
}

class Car
Expand All @@ -21,5 +22,4 @@ class Car
public string Make { get; set; }
public string Model { get; set; }
}
#endregion
}
2 changes: 2 additions & 0 deletions samples/core/Modeling/FluentAPI/KeyComposite.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ class MyContext : DbContext
{
public DbSet<Car> Cars { get; set; }

#region KeyComposite
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Car>()
.HasKey(c => new { c.State, c.LicensePlate });
}
#endregion
}

class Car
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@

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

#region KeyName
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.HasKey(b => b.BlogId)
.HasName("PrimaryKey_BlogId");
}
#endregion
}

public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
}
#endregion
}
2 changes: 2 additions & 0 deletions samples/core/Modeling/FluentAPI/KeySingle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ class MyContext : DbContext
{
public DbSet<Car> Cars { get; set; }

#region KeySingle
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Car>()
.HasKey(c => c.LicensePlate);
}
#endregion
}

class Car
Expand Down

0 comments on commit 68e45d3

Please sign in to comment.