Cosmonaut 2.11.3

A supercharged .NET SDK for Azure CosmosDB with ORM support

Install-Package Cosmonaut -Version 2.11.3
dotnet add package Cosmonaut --version 2.11.3
<PackageReference Include="Cosmonaut" Version="2.11.3" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Cosmonaut --version 2.11.3
The NuGet Team does not provide support for this client. Please contact its maintainers for support.

Cosmonaut

The word was derived from "kosmos" (Ancient Greek: κόσμος) which means world/universe and "nautes" (Ancient Greek: ναῦς) which means sailor/navigator

Cosmonaut is a supercharged SDK with object mapping capabilities that enables .NET developers to work with CosmosDB. It eliminates the need for most of the data-access code that developers usually need to write.

Documentation

Getting started

Samples

Usage

The idea is pretty simple. You can have one CosmosStore per entity (POCO/dtos etc).
This entity will be used to create a collection or use part of a one in CosmosDB and it will offer all the data access for this object.

Registering the CosmosStores in ServiceCollection for DI support

 var cosmosSettings = new CosmosStoreSettings("<<databaseName>>", "<<cosmosUri>>", "<<authkey>>");
                
serviceCollection.AddCosmosStore<Book>(cosmosSettings);

//or just by using the Action extension

serviceCollection.AddCosmosStore<Book>("<<databaseName>>", "<<cosmosUri>>", "<<authkey>>", settings =>
{
    settings.ConnectionPolicy = connectionPolicy;
    settings.DefaultCollectionThroughput = 5000;
    settings.IndexingPolicy = new IndexingPolicy(new RangeIndex(DataType.Number, -1),
        new RangeIndex(DataType.String, -1));
});

//or just initialise the object

ICosmosStore<Book> bookStore = new CosmosStore<Book>(cosmosSettings)

To use the AddCosmosStore extension methods you need to install the Cosmonaut.Extensions.Microsoft.DependencyInjection package.

Install-Package Cosmonaut.Extensions.Microsoft.DependencyInjection
or
dotnet add package Cosmonaut.Extensions.Microsoft.DependencyInjection
Retrieving an entity by id (and partition key)
var user = await cosmosStore.FindAsync("userId");
var user = await cosmosStore.FindAsync("userId", "partitionKey");
var user = await cosmosStore.FindAsync("userId", new RequestOptions());
Querying for entities using LINQ

In order to query for entities all you have to do is call the .Query() method and then use LINQ to create the query you want.
It is HIGHLY recommended that you use one of the Async methods to get the results back, such as ToListAsync or FirstOrDefaultAsync , when available.

var user = await cosmoStore.Query().FirstOrDefaultAsync(x => x.Username == "elfocrash");
var users = await cosmoStore.Query().Where(x => x.HairColor == HairColor.Black).ToListAsync(cancellationToken);
Querying for entities using SQL
// plain sql query
var user = await cosmoStore.Query("select * from c where c.Firstname = 'Smith'").ToListAsync();
or
var user = await cosmoStore.QueryMultipleAsync("select * from c where c.Firstname = 'Smith'");

// or parameterised sql query
var user = await cosmoStore.QueryMultipleAsync("select * from c where c.Firstname = @name", new { name = "Smith" });
Collection sharing

Cosmonaut is all about making integrating with Cosmos DB easy as well as making things such as cost optimisation part of the library.

That's why Cosmonaut supports transparent collection sharing between different types of entities.

Why would you do that?

Cosmos is charging you based on how many RU/s your individual collection is provisioned at. This means that if you don't need to have one collection per entity because you won't use it that much, even on the minimum 400 RU/s, you will be charged money. That's where the magic of schemaless comes in.

How can you do that?

Well it's actually pretty simple. Just implement the ISharedCosmosEntity interface and decorate your object with the SharedCosmosCollection attribute.

The attribute accepts two properties, SharedCollectionName which is mandatory and EntityName which is optional.
The SharedCollectionName property will be used to name the collection that the entity will share with other entities.

The EntityName will be used to make the object identifiable for Cosmosnaut. By default it will pluralize the name of the class, but you can specify it to override this behavior. You can override this by providing your own name by setting the EntityName value at the attribute level.

Once you set this up you can add individual CosmosStores with shared collections.

Collection naming

Your collections will automatically be named based on the plural of the object you are using in the generic type.
However you can override that by decorating the class with the CosmosCollection attribute.

Example:

[CosmosCollection("somename")]

By default you are required to specify your collection name in the attribute level shared entities like this:

[SharedCosmosCollection("shared")]
public class Car : ISharedCosmosEntity
{
    public string Id { get; set; }
    public string CosmosEntityName { get; set; }
}

Even though this is convenient I understand that you might need to have a dynamic way of setting this.
That's why the CosmosStore class has some extra constructors that allow you to specify the overriddenCollectionName property. This property will override any collection name specified at the attribute level and will use that one instead.

Note: If you have specified a CollectionPrefix at the CosmosStoreSettings level it will still be added. You are only overriding the collection name that the attribute would normally set.

Example

Class implementation:

[SharedCosmosCollection("shared")]
public class Car : ISharedCosmosEntity
{
    public string Id { get; set; }
    public string CosmosEntityName { get; set; }
}

CosmosStore initialisation:

var cosmosStore = new CosmosStore<Car>(someSettings, "oldcars");

The outcome of this would be a collection named oldcars because the shared collection name is overridden in the constructor.
There are also method overloads for the same property at the dependency injection extension level.

Cosmonaut

The word was derived from "kosmos" (Ancient Greek: κόσμος) which means world/universe and "nautes" (Ancient Greek: ναῦς) which means sailor/navigator

Cosmonaut is a supercharged SDK with object mapping capabilities that enables .NET developers to work with CosmosDB. It eliminates the need for most of the data-access code that developers usually need to write.

Documentation

Getting started

Samples

Usage

The idea is pretty simple. You can have one CosmosStore per entity (POCO/dtos etc).
This entity will be used to create a collection or use part of a one in CosmosDB and it will offer all the data access for this object.

Registering the CosmosStores in ServiceCollection for DI support

 var cosmosSettings = new CosmosStoreSettings("<<databaseName>>", "<<cosmosUri>>", "<<authkey>>");
                
serviceCollection.AddCosmosStore<Book>(cosmosSettings);

//or just by using the Action extension

serviceCollection.AddCosmosStore<Book>("<<databaseName>>", "<<cosmosUri>>", "<<authkey>>", settings =>
{
    settings.ConnectionPolicy = connectionPolicy;
    settings.DefaultCollectionThroughput = 5000;
    settings.IndexingPolicy = new IndexingPolicy(new RangeIndex(DataType.Number, -1),
        new RangeIndex(DataType.String, -1));
});

//or just initialise the object

ICosmosStore<Book> bookStore = new CosmosStore<Book>(cosmosSettings)

To use the AddCosmosStore extension methods you need to install the Cosmonaut.Extensions.Microsoft.DependencyInjection package.

Install-Package Cosmonaut.Extensions.Microsoft.DependencyInjection
or
dotnet add package Cosmonaut.Extensions.Microsoft.DependencyInjection
Retrieving an entity by id (and partition key)
var user = await cosmosStore.FindAsync("userId");
var user = await cosmosStore.FindAsync("userId", "partitionKey");
var user = await cosmosStore.FindAsync("userId", new RequestOptions());
Querying for entities using LINQ

In order to query for entities all you have to do is call the .Query() method and then use LINQ to create the query you want.
It is HIGHLY recommended that you use one of the Async methods to get the results back, such as ToListAsync or FirstOrDefaultAsync , when available.

var user = await cosmoStore.Query().FirstOrDefaultAsync(x => x.Username == "elfocrash");
var users = await cosmoStore.Query().Where(x => x.HairColor == HairColor.Black).ToListAsync(cancellationToken);
Querying for entities using SQL
// plain sql query
var user = await cosmoStore.Query("select * from c where c.Firstname = 'Smith'").ToListAsync();
or
var user = await cosmoStore.QueryMultipleAsync("select * from c where c.Firstname = 'Smith'");

// or parameterised sql query
var user = await cosmoStore.QueryMultipleAsync("select * from c where c.Firstname = @name", new { name = "Smith" });
Collection sharing

Cosmonaut is all about making integrating with Cosmos DB easy as well as making things such as cost optimisation part of the library.

That's why Cosmonaut supports transparent collection sharing between different types of entities.

Why would you do that?

Cosmos is charging you based on how many RU/s your individual collection is provisioned at. This means that if you don't need to have one collection per entity because you won't use it that much, even on the minimum 400 RU/s, you will be charged money. That's where the magic of schemaless comes in.

How can you do that?

Well it's actually pretty simple. Just implement the ISharedCosmosEntity interface and decorate your object with the SharedCosmosCollection attribute.

The attribute accepts two properties, SharedCollectionName which is mandatory and EntityName which is optional.
The SharedCollectionName property will be used to name the collection that the entity will share with other entities.

The EntityName will be used to make the object identifiable for Cosmosnaut. By default it will pluralize the name of the class, but you can specify it to override this behavior. You can override this by providing your own name by setting the EntityName value at the attribute level.

Once you set this up you can add individual CosmosStores with shared collections.

Collection naming

Your collections will automatically be named based on the plural of the object you are using in the generic type.
However you can override that by decorating the class with the CosmosCollection attribute.

Example:

[CosmosCollection("somename")]

By default you are required to specify your collection name in the attribute level shared entities like this:

[SharedCosmosCollection("shared")]
public class Car : ISharedCosmosEntity
{
    public string Id { get; set; }
    public string CosmosEntityName { get; set; }
}

Even though this is convenient I understand that you might need to have a dynamic way of setting this.
That's why the CosmosStore class has some extra constructors that allow you to specify the overriddenCollectionName property. This property will override any collection name specified at the attribute level and will use that one instead.

Note: If you have specified a CollectionPrefix at the CosmosStoreSettings level it will still be added. You are only overriding the collection name that the attribute would normally set.

Example

Class implementation:

[SharedCosmosCollection("shared")]
public class Car : ISharedCosmosEntity
{
    public string Id { get; set; }
    public string CosmosEntityName { get; set; }
}

CosmosStore initialisation:

var cosmosStore = new CosmosStore<Car>(someSettings, "oldcars");

The outcome of this would be a collection named oldcars because the shared collection name is overridden in the constructor.
There are also method overloads for the same property at the dependency injection extension level.

Release Notes

Please report any issues on Github.

Showing the top 1 GitHub repositories that depend on Cosmonaut:

Repository Stars
Elfocrash/Cosmonaut
🌐 A supercharged .NET SDK for Azure CosmosDB with ORM support

Version History

Version Downloads Last updated
2.11.3 311 7/5/2019
2.10.0 12,617 3/23/2019
2.9.0 2,341 2/28/2019
2.8.2 4,553 1/17/2019
2.8.1 211 1/10/2019
2.7.1 3,386 12/11/2018
2.7.0 7,576 12/3/2018
2.6.2 1,045 11/15/2018
2.5.0 855 11/8/2018
2.4.2 2,560 10/8/2018
2.4.0 1,363 9/24/2018
2.3.2 860 9/20/2018
2.2.0 4,610 9/12/2018
2.0.4 1,522 9/7/2018
2.0.3 519 8/9/2018