Skip to content

unicreo/framework-db-mongodb-repository

Repository files navigation

Unicreo.Framework.Db.MongoDB.Repository

This library is representation of repository pattern in .net core for MongoDB using for internal need of company.

Based on MongoDb.Driver 2.12.4 and .net 5

NuGet

Install

  • Package Manager: Install-Package Unicreo.Framework.Db.MongoDB.Repository -Version 1.0.6
  • .NET CLI: dotnet add package Unicreo.Framework.Db.MongoDB.Repository --version 1.0.6
  • PackageReference <PackageReference Include="Unicreo.Framework.Db.MongoDB.Repository" Version="1.0.6" />

Configure

Use DI for config.

You have to implement ICollectionNameProvider interface that has to implement string GetCollectionName(Type entityType) method which allows to get name of collection in mongodb by type.

Also you have to set connection string to your mongodb.

And you should set logger;

Example:

services.AddTransient<ICollectionNameProvider, CollectionNameProvider>(); // You have to implement this interface by yourself   
services.AddTransient<IMongoDbContext>(sp =>
 {
     string connectionString = "Your connection string";
     ILogger<MongoDbContext> logger = sp.GetRequiredService<ILogger<MongoDbContext>>();
     ICollectionNameProvider collectionNameProvider = sp.GetRequiredService<ICollectionNameProvider>;
     return new MongoDbContext(connectionString, collectionNameProvider);
 });

services.AddTransient<IMongoDbDataRepository, MongoDbDataRepository>();

Usage

All mongodb entities should be inherited from BaseEntity that contain ObjectId as Id.

public class ToDo: BaseEntity {
    public string Name { get; set;}
    public bool Done { get; set; } = false; 
}

Use DI to provide MongoDataRepository

public class ToDoService {
    private readonly IMongoDbDataRepository _dataRepository;

    public ToDoService(IMongoDbDataRepository dataRepository) {
        _dataRepository = dataRepository;
    }
}

Examples

Initialize collections:

var collectionNames = new List<string> {"ToDos", "Users"}; // better way is to get names from CollectionNameProvider
await _dataRepository.Initialize(collectionNames);

Create entity:

var todo = new ToDo { Name = "buy smth"};
await _dataRepository.AddAsync(todo);

Create list:

var todoList = new List<ToDo> {
    new ToDo {Name = "buy smth"},
    new ToDo {Name = "sell smth"}
};

await _dataRepository.AddListAsync(todoList);

Get entity:

string id = ObjectId.GenerateNewId().ToString();
var todo = await _dataRepository.GetDocumentAsync<ToDo>(id); //you should ensure that id is valid ObjectId
var todo = await _dataRepository.GetDocumentAsync<ToDo>(item => item.Id == ObjectId.Parse(id) && !item.Done);

Also in get methods you can use projection

var projection = Builders<ToDo>.Projection
    .Include(entity => entity.Name)
    .Exclude(entity => entity.Done);

var todo = await _dataRepository.GetDocumentAsync<ToDo>(id, projection);

It works for GetList methods too.

GetList:

with pagination

int skip = 10;
int take = 10;
var todoList = await _dataRepository.GetListAsync(skip, take, entry => !entry.Done);

without pagination

var todoList = await _dataRepository.GetListAsync(entry => !entry.Done);

Update:

var todo = await _dataRepository.GetDocumentAsync<ToDo>(id);
todo.Name = "New name";
await _dataRepository.UpdateAsync<ToDo>(todo);

Update one:

allow to update only one property

var todo = await _dataRepository.GetDocumentAsync<ToDo>(id);
await _dataRepository.UpdateOneAsync(todo, entity => entity.Name, "new name");

or you can use builders

var todo = await _dataRepository.GetDocumentAsync<ToDo>(id);
var update = Builders<ToDo>.Update.Set(entity => entity.Name, "new name");
await _dataRepository.UpdateOneAsync(todo, update);

Tip: with builders you can update multiple fields at once

var update = Builders<ToDo>.Update.Set(entity => entity.Name, "new name").Set(entity => entity.Title, "new title");

Update many:

takes documents you want to modify and updates the field in documents with the given value

await _dataRepository.UpdateManyAsync<ToDo, string>(todo => todo.Any(e => e.CreatedDate <= new DateTime.Now), todo => todo.Name, "new name");

this operation sets a new name to all created before todos

the same operation with builders

var update = Builders<ToDo>.Update.Set(entity => entity.Name, "new name");
await _dataRepository.UpdateManyAsync<ToDo>(todo => todo.Any(e => e.CreatedDate <= new DateTime.Now), update);

Tip: if your field is an array and you want to change only one item of this array, you can access the item by passing an index array[index] or use a positional operator - $. The positional $ operator acts as a placeholder for the first element that matches the query document. In C# Mongo.Driver positional operator is array[-1].

var update = Builders<ToDo>.Update.Set(entity => entity.Comments[-1].Message, "new message");
await _dataRepository.UpdateManyAsync<ToDo>(todo => todo.Comments.Any(comment => comment.authorId == userId), update);

this operation sets the message of the first comment with authorId equals userId in all todos

Delete:

var todo = await _dataRepository.GetDocumentAsync<ToDo>(id);
await _dataRepository.DeleteAsync(todo);

Transactions

You also can use transactions

Methods you can use in transactions:

  • AddAsync
  • AddListAsync
  • UpdateAsync
  • UpdateOneAsync
  • UpdateManyAsync
  • DeleteAsync

Note: you should pass session object in every method that you want to use in transaction.

Example:

using (var session = _dataRepository.StartSession())
{
    session.StartTransaction();
    var todo1 = new ToDo {Name = "buy smth"};
    var todo2 = new ToDo {Name = "sell smth"};

    try {
        await _dataRepository.AddAsync(todo1, session);
        await _dataRepository.AddAsync(todo2, session);
        await session.CommitTransactionAsync();        
    }
    catch {
        await session.AbortTransactionAsync();
    }
}

MongoDbContext

For deeper usage of database you can use MongoDbContext that implements next interface:

    interface IMongoDbContext
    {
        IMongoCollection<T> GetCollection<T>();
        IMongoQueryable<T> GetQueryableCollection<T>();
        IMongoDatabase Database { get; }
        IMongoClient Client { get; }
        Task CreateCollectionsAsync(IEnumerable<string> collectionNames);
    }

Information about usage IMongoCollection, IMongoQueryable, IMongoDatabase, IMongoClient you can find here.

About

This library is representation of repository pattern in .net core for MongoDB using for internal need of company

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •  

Languages