using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Dpz.Core.Infrastructure.Entity;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using MongoDB.Driver;
namespace Dpz.Core.MongodbAccess;
public class UnitOfWork : IUnitOfWork
{
private readonly CancellationToken _cancellationToken = new CancellationToken();
private readonly IClientSessionHandle _session;
private readonly string? _connectionString;
[ActivatorUtilitiesConstructor]
public UnitOfWork(IConfiguration configuration)
{
_connectionString = configuration.GetConnectionString("mongodb");
_session = MongodbAccess.StartSession(_connectionString, cancellationToken: _cancellationToken);
}
public UnitOfWork(string? connectionString)
{
_connectionString = connectionString;
_session = MongodbAccess.StartSession(_connectionString, cancellationToken: _cancellationToken);
}
public void Begin()
{
if (!_session.IsInTransaction)
{
_session.StartTransaction();
}
}
private readonly Dictionary<Type, IRepository> _currentUowRepositories = new Dictionary<Type, IRepository>();
public IRepository<T> GetRepository<T>() where T : IBaseEntity, new()
{
var type = typeof(IRepository<T>);
if (_currentUowRepositories.TryGetValue(type, out var value) && value is IRepository<T> currentUowRepository)
{
return currentUowRepository;
}
var access = new MongodbAccess<T>(_connectionString);
IRepository<T> repository = new RepositoryUnitOfWork<T>(access, _session);
_currentUowRepositories.Add(type, repository);
return repository;
}
public IRepository<T> GetRepository<T>(string collectionName) where T : IBaseEntity, new()
{
var type = typeof(IRepository<T>);
if (_currentUowRepositories.TryGetValue(type, out var value) && value is IRepository<T> currentUowRepository)
{
return currentUowRepository;
}
var access = new MongodbAccess<T>(_connectionString, collectionName);
IRepository<T> repository = new RepositoryUnitOfWork<T>(access, _session);
_currentUowRepositories.Add(type, repository);
return repository;
}
public async Task CommitAsync()
{
await _session.CommitTransactionAsync(_cancellationToken);
}
public async Task RollbackAsync()
{
await _session.AbortTransactionAsync(_cancellationToken);
}
private bool _disposed;
private void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
_session.Dispose();
}
_disposed = true;
}
}
~UnitOfWork()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}