Init Git
This commit is contained in:
64
AMREZ.EOP.Infrastructures/Storage/DbScope.cs
Normal file
64
AMREZ.EOP.Infrastructures/Storage/DbScope.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using System.Collections.Concurrent;
|
||||
using AMREZ.EOP.Abstractions.Applications.Tenancy;
|
||||
using AMREZ.EOP.Abstractions.Storage;
|
||||
using AMREZ.EOP.Infrastructures.Data;
|
||||
using AMREZ.EOP.Infrastructures.Options;
|
||||
using Microsoft.Extensions.Options;
|
||||
using StackExchange.Redis;
|
||||
using IDatabase = Microsoft.EntityFrameworkCore.Storage.IDatabase;
|
||||
|
||||
namespace AMREZ.EOP.Infrastructures.Storage;
|
||||
|
||||
public sealed class DbScope : IDbScope, IAsyncDisposable
|
||||
{
|
||||
private readonly ITenantDbContextFactory _factory;
|
||||
private readonly IOptions<AuthOptions> _opts;
|
||||
private readonly IConnectionMultiplexer? _redis;
|
||||
private readonly ConcurrentDictionary<Type, object> _cache = new();
|
||||
|
||||
public DbScope(ITenantDbContextFactory factory, IOptions<AuthOptions> opts, IConnectionMultiplexer? redis = null)
|
||||
{ _factory = factory; _opts = opts; _redis = redis; }
|
||||
|
||||
private ITenantContext? _tenant;
|
||||
|
||||
public void EnsureForTenant(ITenantContext tenant)
|
||||
{
|
||||
if (_tenant?.Id == tenant.Id) return;
|
||||
_tenant = tenant;
|
||||
_cache.Clear();
|
||||
var ef = _factory.Create<AppDbContext>(tenant);
|
||||
_cache[typeof(AppDbContext)] = ef;
|
||||
if (_redis != null)
|
||||
_cache[typeof(IDatabase)] = _redis.GetDatabase(_opts.Value.RedisDb);
|
||||
}
|
||||
|
||||
public TContext Get<TContext>() where TContext : class
|
||||
{
|
||||
if (_tenant is null) throw new InvalidOperationException("Tenant not set. Call EnsureForTenant first.");
|
||||
if (_cache.TryGetValue(typeof(TContext), out var obj)) return (TContext)obj;
|
||||
|
||||
if (typeof(TContext) == typeof(AppDbContext))
|
||||
{
|
||||
var ef = _factory.Create<AppDbContext>(_tenant);
|
||||
_cache[typeof(AppDbContext)] = ef;
|
||||
return (TContext)(object)ef;
|
||||
}
|
||||
|
||||
if (typeof(TContext) == typeof(IDatabase))
|
||||
{
|
||||
if (_redis is null) throw new InvalidOperationException("Redis not configured");
|
||||
var db = _redis.GetDatabase(_opts.Value.RedisDb);
|
||||
_cache[typeof(IDatabase)] = db;
|
||||
return (TContext)(object)db;
|
||||
}
|
||||
|
||||
throw new NotSupportedException($"Unknown context type {typeof(TContext).Name}");
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
if (_cache.TryGetValue(typeof(AppDbContext), out var ef) && ef is AppDbContext db)
|
||||
await db.DisposeAsync();
|
||||
_cache.Clear();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user