Skip to content

Commit bc137e0

Browse files
authored
(CommunityToolkit#304) Documentation for Cosmos SDK provider (CommunityToolkit#307)
* (CommunityToolkit#304) Documentation for Cosmos SDK provider * (CommunityToolkit#304) Added attribution
1 parent cee465f commit bc137e0

File tree

4 files changed

+150
-26
lines changed

4 files changed

+150
-26
lines changed

docs/in-depth/server/db/cosmos-sdk.md

+128
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
# Cosmos (SDK)
2+
3+
Support for Cosmos DB is available in two flavors:
4+
5+
* via [Entity Framework Core](./cosmos.md) - see [EF Core Azure Cosmos DB Provider](https://learn.microsoft.com/ef/core/providers/cosmos/)
6+
* via the Cosmos DB SDK (this document) - see [the official documentation](https://learn.microsoft.com/azure/cosmos-db/nosql/quickstart-dotnet)
7+
8+
There are differences between the two providers that impact how you configure the container and the operations that are available.
9+
10+
Use the [CommunityToolkit.Datasync.Server.CosmosDb](https://www.nuget.org/packages/CommunityToolkit.Datasync.Server.CosmosDb) package to add support for this repository.
11+
12+
Azure Cosmos DB is a fully managed NoSQL database for high-performance applications of any size or scale. See [Azure Cosmos DB for NoSQL .NET SDK](https://learn.microsoft.com/azure/cosmos-db/nosql/quickstart-dotnet) for information on using Azure Cosmos DB via the SDK.
13+
14+
!!! info
15+
The Cosmos DB library and sample has been kindly contributed to the community by [@richard-einfinity](https://github.com/richard-einfinity).
16+
17+
## Set up
18+
19+
1. Set up the Cosmos Container with a composite index that specifies the `UpdatedAt` and `Id` fields. Composite indices can be added to a container through the Azure portal, ARM, Bicep, Terraform, or within code. Here's an example [bicep](https://learn.microsoft.com/azure/azure-resource-manager/bicep/overview) resource definition that would store all datasync entities in the same container:
20+
21+
resource container 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers@2022-05-15' = {
22+
parent: database
23+
name: containerName
24+
properties: {
25+
resource: {
26+
id: containerName
27+
partitionKey: {
28+
paths: [ '/entity' ]
29+
kind: 'Hash'
30+
}
31+
indexingPolicy: {
32+
indexingMode: 'consistent'
33+
includedPaths: [ { path: '/*' } ]
34+
excludedPaths: [ { path: '/_etag/?' } ]
35+
compositeIndexes: [
36+
[
37+
{ path: '/updatedAt', order: 'ascending' }
38+
{ path: '/id', order: 'ascending' }
39+
]
40+
]
41+
}
42+
}
43+
}
44+
}
45+
46+
You must include a composite index for each combination of filters that you require. A "client-side evaluation" exception will be generated (which is turned into a `400 Bad Request` by the server) if you do not have the appropriate composite indices for the request.
47+
48+
You can also review the [bicep module](https://github.com/CommunityToolkit/Datasync/blob/main/samples/datasync-server-cosmosdb-singlecontainer/infra/resources.bicep) that is used in the sample.
49+
50+
If you pull a subset of items in the table, ensure you specify all properties involved in the query.
51+
52+
2. Create an appropriate model that inherits from `CosmosTableData<TEntity>`:
53+
54+
public class TodoItem : CosmosTableData<TodoItem>
55+
{
56+
[Required, MinLength(1)]
57+
public string Title { get; set; } = string.Empty;
58+
59+
public bool IsComplete { get; set; }
60+
}
61+
62+
3. In `Program.cs`, configure a `CosmosClient` and add this to the services collection as a singleton:
63+
64+
CosmosClient cosmosClient = new CosmosClient(connectionString, new CosmosClientOptions()
65+
{
66+
UseSystemTextJsonSerializerWithOptions = new()
67+
{
68+
Converters =
69+
{
70+
new JsonStringEnumConverter(),
71+
new DateTimeOffsetConverter(),
72+
new DateTimeConverter(),
73+
new TimeOnlyConverter(),
74+
new SpatialGeoJsonConverter()
75+
},
76+
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
77+
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull | JsonIgnoreCondition.WhenWritingDefault,
78+
NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals,
79+
ReferenceHandler = ReferenceHandler.Preserve
80+
}
81+
});
82+
83+
You can obtain the connection string from the Cosmos resource page within the Azure Portal.
84+
85+
4. Create an `ICosmosTableOptions<TEntity>` object for each entity you wish to use for datasync purposes. The library provides two implementations:
86+
87+
* `CosmosSharedTableOptions<TEntity>` stores entities in a single container using a partition key based on the entity name.
88+
* `CosmosSingleTableOptions<TEntity>` stores entities by compressing the ID and partition key into the ID of the entity.
89+
90+
You can also specify your own implementation for custom logic in determining the partition key and ID. Add the `ICosmosTableOptions<TEntity>` objects to the services collection in `Program.cs`:
91+
92+
builder.Services.AddSingleton<ICosmosTableOptions<TodoItem>>(new CosmosSharedTableOptions<TodoItem>("TodoDb", "TodoContainer"));
93+
builder.Services.AddSingleton<ICosmosTableOptions<TodoList>>(new CosmosSharedTableOptions<TodoList>("TodoDb", "TodoContainer"));
94+
95+
5. Add the Cosmos repositories to the services collection within `Program.cs` with the following code:
96+
97+
builder.Services.AddSingleton(typeof(IRepository<>), typeof(CosmosTableRepository<>));
98+
builder.Services.AddDatasyncServices();
99+
100+
6. Create a controller for each datasync entity:
101+
102+
[Route("tables/[controller]")]
103+
public class TodoItemController : TableController<TodoItem>
104+
{
105+
public TodoItemController(IRepository<TodoItem> repository) : base(repository)
106+
{
107+
}
108+
}
109+
110+
You may add other settings to the repository to enable access control providers, logging, and other advanced features. For more information, see the [documentation on the TableController](../index.md#table-controller-options).
111+
112+
## Avoid Client-side evaluations
113+
114+
When constructing a query within a client, avoid the following:
115+
116+
* Math operations such as division, multiplication, floor, ceiling, and round.
117+
* Accessing date/time components such as year, day, or month.
118+
* The use of DateOnly and TimeOnly types.
119+
120+
These are not supported by the query provider for Cosmos DB. Using them will result in a client-side evaluation. Client-side evaluations are not supported and will result in a `400 Bad Request` or `500 Internal Server Error`.
121+
122+
## Support and further information
123+
124+
Azure Cosmos DB is supported in the `Microsoft.AspNetCore.Datasync.CosmosDb` NuGet package since v9.0.1. For more information, review the following links:
125+
126+
* [Azure Cosmos DB .NET SDK](https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/quickstart-dotnet) documentation.
127+
* [Cosmos DB index policy](https://learn.microsoft.com/azure/cosmos-db/index-policy) documentation.
128+
* [Cosmos DB single container reference sample](https://github.com/CommunityToolkit/Datasync/tree/main/samples/datasync-server-cosmosdb-singlecontainer)

docs/in-depth/server/db/cosmos.md

+14-23
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
1-
# Cosmos (via EF Core)
1+
# Cosmos (EF Core)
22

3-
Cosmos is configured via Entity Framework Core. Use the [CommunityToolkit.Datasync.Server.EntityFrameworkCore](https://www.nuget.org/packages/CommunityToolkit.Datasync.Server.EntityFrameworkCore) package to add support for this repository.
3+
Support for Cosmos DB is available in two flavors:
4+
5+
* via Entity Framework Core (this document) - see [EF Core Azure Cosmos DB Provider](https://learn.microsoft.com/ef/core/providers/cosmos/)
6+
* via [the Cosmos DB SDK](./cosmos-sdk.md) - see [the official documentation](https://learn.microsoft.com/azure/cosmos-db/nosql/quickstart-dotnet)
7+
8+
There are differences between the two providers that impact how you configure the container and the operations that are available.
9+
10+
Cosmos DB is configured via Entity Framework Core. Use the [CommunityToolkit.Datasync.Server.EntityFrameworkCore](https://www.nuget.org/packages/CommunityToolkit.Datasync.Server.EntityFrameworkCore) package to add support for this repository.
411

512
Azure Cosmos DB is a fully managed NoSQL database for high-performance applications of any size or scale. See [Azure Cosmos DB Provider](https://learn.microsoft.com/ef/core/providers/cosmos/) for information on using Azure Cosmos DB with Entity Framework Core. When using Azure Cosmos DB with the Datasync Community Toolkit:
613

@@ -15,34 +22,18 @@ Azure Cosmos DB is a fully managed NoSQL database for high-performance applicati
1522
resource: {
1623
id: 'TodoItems'
1724
partitionKey: {
18-
paths: [
19-
'/Id'
20-
]
25+
paths: [ '/Id' ]
2126
kind: 'Hash'
2227
}
2328
indexingPolicy: {
2429
indexingMode: 'consistent'
2530
automatic: true
26-
includedPaths: [
27-
{
28-
path: '/*'
29-
}
30-
]
31-
excludedPaths: [
32-
{
33-
path: '/"_etag"/?'
34-
}
35-
]
31+
includedPaths: [ { path: '/*' } ]
32+
excludedPaths: [ { path: '/"_etag"/?' } ]
3633
compositeIndexes: [
3734
[
38-
{
39-
path: '/UpdatedAt'
40-
order: 'ascending'
41-
}
42-
{
43-
path: '/Id'
44-
order: 'ascending'
45-
}
35+
{ path: '/UpdatedAt', order: 'ascending' }
36+
{ path: '/Id', order: 'ascending' }
4637
]
4738
]
4839
}

docs/in-depth/server/index.md

+7-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ The datasync service support a number of backend database servers, and allows fo
1919

2020
Default repository implementations are provided for Entity Framework Core, LiteDB, an in-memory store, and an Automapper store. For specific database support, see the following:
2121

22-
* [Azure Cosmos DB](./db/cosmos.md)
22+
* Azure Cosmos DB ([EFCore](./db/cosmos.md) and [SDK](./db/cosmos-sdk.md))
2323
* [Azure SQL and SQL Server](./db/azuresql.md)
2424
* [In Memory Datastore](./db/in-memory.md)
2525
* [LiteDb](./db/litedb.md)
@@ -60,9 +60,13 @@ Ensure you map the controllers when setting up your HTTP middleware pipeline. Y
6060

6161
All model classes must implement `ITableData`. Each repository type has an abstract class that implements `ITableData` and provides additional functionality to the repository. For example, the Entity Framework Core repository provides:
6262

63-
* `SqliteEntityTableData` for Sqlite.
63+
* `InMemoryTableData` for an in-memory data store.
64+
* `LiteDbTableData` for a LiteDb based store.
6465
* `CosmosEntityTableData` for Cosmos Db support via EF Core.
65-
* `EntityTableData` for other EF-Core based database connections.
66+
* `CosmosTableData` for Cosmos Db support via the Cosmos DB SDK.
67+
* `EntityTableData` for most EF-Core based database providers.
68+
* `MongoTableData` for Mongo DB (via the MongoDB SDK).
69+
* `SqliteEntityTableData` for Sqlite.
6670

6771
A typical "TodoItem" entity for PostgreSQL would look like this:
6872

mkdocs.shared.yml

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ nav:
4141
- Databases:
4242
- Azure SQL: in-depth/server/db/azuresql.md
4343
- "CosmosDB (EFCore)": in-depth/server/db/cosmos.md
44+
- "CosmosDB (SDK)": in-depth/server/db/cosmos-sdk.md
4445
- In Memory: in-depth/server/db/in-memory.md
4546
- LiteDb: in-depth/server/db/litedb.md
4647
- MongoDb: in-depth/server/db/mongodb.md

0 commit comments

Comments
 (0)