Skip to content

Commit

Permalink
Fix line ranges/regions (#3050)
Browse files Browse the repository at this point in the history
Fixes #3048
Fixes #3049
roji authored Feb 3, 2021
1 parent d0d2444 commit 3dffa15
Showing 6 changed files with 22 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -24,15 +24,15 @@ In most database systems, a default collation is defined at the database level;

When using EF Core migrations to manage your database schema, the following in your model's `OnModelCreating` method configures a SQL Server database to use a case-sensitive collation:

[!code-csharp[Main](../../../samples/core/Miscellaneous/Collations/Program.cs?range=40)]
[!code-csharp[Main](../../../samples/core/Miscellaneous/Collations/Program.cs?name=DatabaseCollation)]

## Column collation

Collations can also be defined on text columns, overriding the database default. This can be useful if certain columns need to be case-insensitive, while the rest of the database needs to be case-sensitive.

When using EF Core migrations to manage your database schema, the following configures the column for the `Name` property to be case-insensitive in a database that is otherwise configured to be case-sensitive:

[!code-csharp[Main](../../../samples/core/Miscellaneous/Collations/Program.cs?name=OnModelCreating&highlight=6)]
[!code-csharp[Main](../../../samples/core/Miscellaneous/Collations/Program.cs?name=ColumnCollation)]

## Explicit collation in a query

Original file line number Diff line number Diff line change
@@ -22,7 +22,7 @@ The main documentation on required and optional properties and their interaction

When nullable reference types are enabled, the C# compiler emits warnings for any uninitialized non-nullable property, as these would contain null. As a result, the following, common way of writing entity types cannot be used:

[!code-csharp[Main](../../../samples/core/Miscellaneous/NullableReferenceTypes/CustomerWithWarning.cs?name=CustomerWithWarning&highlight=4-5)]
[!code-csharp[Main](../../../samples/core/Miscellaneous/NullableReferenceTypes/CustomerWithWarning.cs?name=CustomerWithWarning&highlight=5-6)]

[Constructor binding](xref:core/modeling/constructors) is a useful technique to ensure that your non-nullable properties are initialized:

@@ -59,11 +59,11 @@ Another strategy is to use non-nullable auto-properties, but to initialize them

When dealing with optional relationships, it's possible to encounter compiler warnings where an actual null reference exception would be impossible. When translating and executing your LINQ queries, EF Core guarantees that if an optional related entity does not exist, any navigation to it will simply be ignored, rather than throwing. However, the compiler is unaware of this EF Core guarantee, and produces warnings as if the LINQ query were executed in memory, with LINQ to Objects. As a result, it is necessary to use the null-forgiving operator (!) to inform the compiler that an actual null value isn't possible:

[!code-csharp[Main](../../../samples/core/Miscellaneous/NullableReferenceTypes/Program.cs?range=46)]
[!code-csharp[Main](../../../samples/core/Miscellaneous/NullableReferenceTypes/Program.cs?name=Navigating)]

A similar issue occurs when including multiple levels of relationships across optional navigations:

[!code-csharp[Main](../../../samples/core/Miscellaneous/NullableReferenceTypes/Program.cs?range=36-39&highlight=2)]
[!code-csharp[Main](../../../samples/core/Miscellaneous/NullableReferenceTypes/Program.cs?name=Including&highlight=2)]

If you find yourself doing this a lot, and the entity types in question are predominantly (or exclusively) used in EF Core queries, consider making the navigation properties non-nullable, and to configure them as optional via the Fluent API or Data Annotations. This will remove all compiler warnings while keeping the relationship optional; however, if your entities are traversed outside of EF Core, you may observe null values although the properties are annotated as non-nullable.

14 changes: 7 additions & 7 deletions entity-framework/core/modeling/entity-properties.md
Original file line number Diff line number Diff line change
@@ -51,11 +51,11 @@ You can also configure your columns to specify an exact data type for a column.

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

[!code-csharp[Main](../../../samples/core/Modeling/DataAnnotations/ColumnDataType.cs?name=ColumnDataType&highlight=4,6)]
[!code-csharp[Main](../../../samples/core/Modeling/DataAnnotations/ColumnDataType.cs?name=ColumnDataType&highlight=5,8)]

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

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

***

@@ -70,7 +70,7 @@ In the following example, configuring a maximum length of 500 will cause a colum

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

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

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

@@ -119,7 +119,7 @@ The following example shows an entity type with required and optional properties

#### [Without NRT (default)](#tab/without-nrt)

[!code-csharp[Main](../../../samples/core/Miscellaneous/NullableReferenceTypes/CustomerWithoutNullableReferenceTypes.cs?name=Customer&highlight=4-8)]
[!code-csharp[Main](../../../samples/core/Miscellaneous/NullableReferenceTypes/CustomerWithoutNullableReferenceTypes.cs?name=Customer&highlight=5,8)]

#### [With NRT](#tab/with-nrt)

@@ -140,7 +140,7 @@ A property that would be optional by convention can be configured to be required

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

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

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

@@ -155,7 +155,7 @@ A property that would be optional by convention can be configured to be required
A collation can be defined on text columns, determining how they are compared and ordered. For example, the following code snippet configures a SQL Server column to be case-insensitive:

[!code-csharp[Main](../../../samples/core/Miscellaneous/Collations/Program.cs?range=42-43)]
[!code-csharp[Main](../../../samples/core/Miscellaneous/Collations/Program.cs?name=ColumnCollation)]

If all columns in a database need to use a certain collation, define the collation at the database level instead.

@@ -170,7 +170,7 @@ You can set an arbitrary text comment that gets set on the database column, allo
> [!NOTE]
> Setting comments via data annotations was introduced in EF Core 5.0.
[!code-csharp[Main](../../../samples/core/Modeling/DataAnnotations/ColumnComment.cs?name=ColumnComment&highlight=4)]
[!code-csharp[Main](../../../samples/core/Modeling/DataAnnotations/ColumnComment.cs?name=ColumnComment&highlight=5)]

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

4 changes: 2 additions & 2 deletions entity-framework/core/modeling/generated-properties.md
Original file line number Diff line number Diff line change
@@ -47,7 +47,7 @@ We saw above that EF Core automatically sets up value generation for primary key

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

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

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

@@ -59,7 +59,7 @@ Similarly, a property can be configured to have its value generated on add or up

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

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

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

6 changes: 4 additions & 2 deletions samples/core/Miscellaneous/Collations/Program.cs
Original file line number Diff line number Diff line change
@@ -33,15 +33,17 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=EFCollations;Trusted_Connection=True;ConnectRetryCount=0");
}

#region OnModelCreating
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
#region DatabaseCollation
modelBuilder.UseCollation("SQL_Latin1_General_CP1_CS_AS");
#endregion

#region ColumnCollation
modelBuilder.Entity<Customer>().Property(c => c.Name)
.UseCollation("SQL_Latin1_General_CP1_CI_AS");
#endregion
}
#endregion
}

public class Customer
4 changes: 4 additions & 0 deletions samples/core/Miscellaneous/NullableReferenceTypes/Program.cs
Original file line number Diff line number Diff line change
@@ -34,17 +34,21 @@ private static void Main(string[] args)
var john = context.Customers.First(c => c.FirstName == "John");
Console.WriteLine("John's last name: " + john.LastName);

#region Including
var order = context.Orders
.Include(o => o.OptionalInfo!)
.ThenInclude(op => op.ExtraAdditionalInfo)
.Single();
#endregion

// The following would be a programming bug: we forgot to include ShippingAddress above. It would throw InvalidOperationException.
// Console.WriteLine(order.ShippingAddress.City);
// The following would be a programming bug: we forgot to include Product above; will throw NullReferenceException. It would throw NullReferenceException.
// Console.WriteLine(order.Product.Name);

#region Navigating
Console.WriteLine(order.OptionalInfo!.ExtraAdditionalInfo!.SomeExtraAdditionalInfo);
#endregion
}
}
}

0 comments on commit 3dffa15

Please sign in to comment.