A generic implementation of Repository Pattern in C# to Cosmos DB SQL API
This project implements and demonstrates how to use the repository pattern with Azure Cosmos DB SQL API.
Martin Fowler describes in the book Patterns of Enterprise Application Architecture a repository as follows:
A repository performs the tasks of an intermediary between the domain model layers and data mapping, acting in a similar way to a set of domain objects in memory. Client objects declaratively build queries and send them to the repositories for answers. Conceptually, a repository encapsulates a set of objects stored in the database and operations that can be performed on them, providing a way that is closer to the persistence layer. Repositories, also, support the purpose of separating, clearly and in one direction, the dependency between the work domain and the data allocation or mapping.
- Centralizes data, business and service logic.
- Unit tests independent off the database layer.
- Modify the data access logic or business access logic without change the repository logic.
Generic repository pattern is aimed at reducing repetition replacing it with abstractions or using data normalization - Don’t repeat yourself
I've separated some articles for you to decide for yourself.
- Repository Pattern Benefits: Why We Should Consider It
- The generic repository is just a lazy anti-pattern
- What are the benefits of using Repositories?
- Ditch the Repository Pattern Already
Azure Cosmos DB is Microsoft's globally distributed, multi-model database service and enables you to using your favorite API among SQL, MongoDB, Cassandra, Tables, or Gremlin.
- Installation process
To install Cosmos.Db.Sql.Api.Repository, run the following command in the Package Manager Console
PM> Install-Package Cosmos.Db.Sql.Api.Repository -Version 1.0.0-preview
Cosmos.Db.Sql.Api.Repository has GenericRepository. Through CosmosClient (preview) GenericRepository class implement base CRUD methods (AddAsync, UpdateAsync, DeleteAsync, GetByIdAsync, GetAllAsyn).
- Software dependencies
Cosmos.Db.Sql.Api.Repository have Cosmos.Db.Sql.Api.Domain dependency. The domain layer have IGenericRepository and Entity base class.
public abstract class Entity
{
/// <summary>
/// Default document entity identifier
/// </summary>
[JsonProperty(PropertyName = "id")]
public string Id { get; set; }
/// <summary>
/// Data time to live
/// </summary>
[JsonProperty(PropertyName = "ttl")]
public int Ttl { get; set; }
/// <summary>
/// Entity
/// </summary>
/// <param name="generateId">Generate id</param>
public Entity(bool generateId)
{
SetDefaultTimeToLive();
if (generateId)
this.Id = Guid.NewGuid().ToString();
}
/// <summary>
/// Set a default data time to live
/// </summary>
public virtual void SetDefaultTimeToLive()
{
Ttl = -1;
}
}
After install Cosmos.Db.Core.Repository you need:
- Create Entity
Entity is a Document (JSON) data. Ex:
public class Foo : Entity
{
public Foo()
: base(true)
{
}
public string City { get; set; }
public string Neighborhood { get; set; }
}
- Create Repository interface
public interface IFooRepository : IGenericRepository<Foo>
{
}
- Implement Repository
public class FooRepository : GenericRepository<Domain.Entities.Foo>, IFooRepository
{
public readonly CosmosClient _cosmosClient;
public FooRepository(CosmosClient cosmosClient) :
base(cosmosClient)
{
_cosmosClient = cosmosClient;
}
public override string DatabaseId => "Foo";
public override string ContainerId => "Foo";
}
- Configure Dependecy Injection
public void ConfigureServices(IServiceCollection services)
{
services
.AddScoped<IFooRepository>(x => new FooRepository(new CosmosClient(
Configuration.GetConnectionString("DefaultConnection"))));
}
See the Foo Project sample which contains implementation. Run Foo.Ui.Api and execute postman (postman-collection.json).
This software is open source, licensed under the MIT License.
See LICENSE for details.