Skip to content

Commit

Permalink
Document Cosmos throughput configuration
Browse files Browse the repository at this point in the history
Document basic support for collections of primitive types in Cosmos

Fixes #3597
Fixes #3358
  • Loading branch information
AndriySvyryd committed Jan 12, 2022
1 parent 3fcf2ad commit acd1d99
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 5 deletions.
112 changes: 111 additions & 1 deletion entity-framework/core/providers/cosmos/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Azure Cosmos DB Provider - EF Core
description: Documentation for the database provider that allows Entity Framework Core to be used with the Azure Cosmos DB SQL API
author: AndriySvyryd
ms.date: 11/15/2021
ms.date: 01/11/2022
uid: core/providers/cosmos/index
---
# EF Core Azure Cosmos DB Provider
Expand Down Expand Up @@ -103,8 +103,33 @@ Once configured the partition key property should always have a non-null value.
It is generally recommended to add the partition key to the primary key as that best reflects the server semantics and allows some optimizations, for example in `FindAsync`.

### Provisioned throughput

If you use EF Core to create the Azure Cosmos database or containers you can configure [provisioned throughput](/azure/cosmos-db/set-throughput) for the database by calling <xref:Microsoft.EntityFrameworkCore.CosmosModelBuilderExtensions.HasAutoscaleThroughput%2A?displayProperty=nameWithType> or <xref:Microsoft.EntityFrameworkCore.CosmosModelBuilderExtensions.HasManualThroughput%2A?displayProperty=nameWithType>. For example:

<!--
modelBuilder.HasManualThroughput(2000);
modelBuilder.HasAutoscaleThroughput(4000);
-->
[!code-csharp[ModelThroughput](../../../../samples/core/Miscellaneous/NewInEFCore6.Cosmos/CosmosModelConfigurationSample.cs?name=ModelThroughput)]

To configure provisioned throughput for a container call <xref:Microsoft.EntityFrameworkCore.CosmosEntityTypeBuilderExtensions.HasAutoscaleThroughput%2A?displayProperty=nameWithType> or <xref:Microsoft.EntityFrameworkCore.CosmosEntityTypeBuilderExtensions.HasManualThroughput%2A?displayProperty=nameWithType>. For example:

<!--
modelBuilder.Entity<Family>(
entityTypeBuilder =>
{
entityTypeBuilder.HasManualThroughput(5000);
entityTypeBuilder.HasAutoscaleThroughput(3000);
});
-->
[!code-csharp[EntityTypeThroughput](../../../../samples/core/Miscellaneous/NewInEFCore6.Cosmos/CosmosModelConfigurationSample.cs?name=EntityTypeThroughput)]

## Embedded entities

> [!NOTE]
> Beginning with EF Core 6.0 related entity types are configured as owned by default. To prevent this for a specific entity type call <xref:Microsoft.EntityFrameworkCore.ModelBuilder.Entity%2A?displayProperty=nameWithType>.
For Cosmos, owned entities are embedded in the same item as the owner. To change a property name use [ToJsonProperty](/dotnet/api/Microsoft.EntityFrameworkCore.CosmosEntityTypeBuilderExtensions.ToJsonProperty):

[!code-csharp[PropertyNames](../../../../samples/core/Cosmos/ModelBuilding/OrderContext.cs?name=PropertyNames)]
Expand Down Expand Up @@ -169,6 +194,91 @@ Internally EF Core always needs to have unique key values for all tracked entiti
> [!TIP]
> When necessary the default primary key for the owned entity types can be changed, but then key values should be provided explicitly.
### Collections of primitive types

Collections of supported primitive types, such as `string` and `int`, are discovered and mapped automatically. Supported collections are all types that implement <xref:System.Collections.Generic.IReadOnlyList%601> or <xref:System.Collections.Generic.IReadOnlyDictionary%602>. For example, consider this entity type:

<!--
public class Book
{
public Guid Id { get; set; }
public string Title { get; set; }
public IList<string> Quotes { get; set; }
public IDictionary<string, string> Notes { get; set; }
}
-->
[!code-csharp[BookEntity](../../../../samples/core/Miscellaneous/NewInEFCore6.Cosmos/CosmosPrimitiveTypesSample.cs?name=BookEntity)]

Both the list and the dictionary can be populated and inserted into the database in the normal way:

<!--
using var context = new BooksContext();
var book = new Book
{
Title = "How It Works: Incredible History",
Quotes = new List<string>
{
"Thomas (Tommy) Flowers was the British engineer behind the design of the Colossus computer.",
"Invented originally for Guinness, plastic widgets are nitrogen-filled spheres.",
"For 20 years after its introduction in 1979, the Walkman dominated the personal stereo market."
},
Notes = new Dictionary<string, string>
{
{ "121", "Fridges" },
{ "144", "Peter Higgs" },
{ "48", "Saint Mark's Basilica" },
{ "36", "The Terracotta Army" }
}
};
context.Add(book);
context.SaveChanges();
-->
[!code-csharp[Insert](../../../../samples/core/Miscellaneous/NewInEFCore6.Cosmos/CosmosPrimitiveTypesSample.cs?name=Insert)]

This results in the following JSON document:

```json
{
"Id": "0b32283e-22a8-4103-bb4f-6052604868bd",
"Discriminator": "Book",
"Notes": {
"36": "The Terracotta Army",
"48": "Saint Mark's Basilica",
"121": "Fridges",
"144": "Peter Higgs"
},
"Quotes": [
"Thomas (Tommy) Flowers was the British engineer behind the design of the Colossus computer.",
"Invented originally for Guinness, plastic widgets are nitrogen-filled spheres.",
"For 20 years after its introduction in 1979, the Walkman dominated the personal stereo market."
],
"Title": "How It Works: Incredible History",
"id": "Book|0b32283e-22a8-4103-bb4f-6052604868bd",
"_rid": "t-E3AIxaencBAAAAAAAAAA==",
"_self": "dbs/t-E3AA==/colls/t-E3AIxaenc=/docs/t-E3AIxaencBAAAAAAAAAA==/",
"_etag": "\"00000000-0000-0000-9b50-fc769dc901d7\"",
"_attachments": "attachments/",
"_ts": 1630075016
}
```

These collections can then be updated, again in the normal way:

<!--
book.Quotes.Add("Pressing the emergency button lowered the rods again.");
book.Notes["48"] = "Chiesa d'Oro";
context.SaveChanges();
-->
[!code-csharp[Updates](../../../../samples/core/Miscellaneous/NewInEFCore6.Cosmos/CosmosPrimitiveTypesSample.cs?name=Updates)]

Limitations:

* Only dictionaries with string keys are supported
* Querying into the contents of primitive collections is not currently supported. Vote for [#16926](https://github.com/dotnet/efcore/issues/16926), [#25700](https://github.com/dotnet/efcore/issues/25700), and [#25701](https://github.com/dotnet/efcore/issues/25701) if these features are important to you.

## Working with disconnected entities

Every item needs to have an `id` value that is unique for the given partition key. By default EF Core generates the value by concatenating the discriminator and the primary key values, using '|' as a delimiter. The key values are only generated when an entity enters the `Added` state. This might pose a problem when [attaching entities](xref:core/saving/disconnected-entities) if they don't have an `id` property on the .NET type to store the value.
Expand Down
2 changes: 1 addition & 1 deletion entity-framework/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@
- name: Overview
href: core/dbcontext-configuration/index.md
- name: Context pooling
href: core/performance/advanced-performance-topics#dbcontext-pooling
href: core/performance/advanced-performance-topics.md#dbcontext-pooling

- name: Create a model
items:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,15 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)

#region ModelThroughput
modelBuilder.HasManualThroughput(2000);
modelBuilder.HasAutoscaleThroughput(6000);
modelBuilder.HasAutoscaleThroughput(4000);
#endregion

#region EntityTypeThroughput
modelBuilder.Entity<Family>(
entityTypeBuilder =>
{
entityTypeBuilder.HasManualThroughput(3000);
entityTypeBuilder.HasAutoscaleThroughput(12000);
entityTypeBuilder.HasManualThroughput(5000);
entityTypeBuilder.HasAutoscaleThroughput(3000);
});
#endregion

Expand Down

0 comments on commit acd1d99

Please sign in to comment.