Mango.Nop.Libraries/Mango.Nop.Core/Repositories/MgDbContextBase.cs

156 lines
5.4 KiB
C#

using System.Transactions;
using AyCode.Core.Consts;
using AyCode.Core.Helpers;
using AyCode.Core.Loggers;
using AyCode.Utils.Extensions;
using Mango.Nop.Core.Interfaces;
using Mango.Nop.Core.Loggers;
using Mango.Nop.Services;
using Nop.Core.Caching;
using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.Orders;
using Nop.Data;
namespace Mango.Nop.Core.Repositories;
public abstract class MgDbContextBase : IMgDbContextBase
{
//TODO: ez itt nem ay igazi, kitalálni vmit! - J.
private readonly CacheKey _auctionAllKey = new("Nop.auction.all-{0}", AUCTION_PATTERN_KEY);
public const string AUCTION_PATTERN_KEY = "Nop.auction.";
protected readonly IMgLockService LockService;
public ILogger Logger { get; init; }
public INopDataProvider DataProvider { get; init; }
public IRepository<Order> Orders { get; set; }
public IRepository<OrderItem> OrderItems { get; set; }
public IRepository<Product> Products { get; set; }
//public IHttpContextAccessor HttpContextAccessor { get; init; }
public MgDbContextBase(IRepository<Product> productRepository, IRepository<Order> orderRepository, IRepository<OrderItem> orderItemRepository, INopDataProvider dataProvider, IMgLockService lockService, ILogger logger)
{
LockService = lockService;
Logger = logger;// new Logger<MgDbContextBase>(logWriters.ToArray());
DataProvider = dataProvider;
Products = productRepository;
Orders = orderRepository;
OrderItems = orderItemRepository;
}
private static TransactionScope CreateTransactionScope(TransactionScopeOption transactionScopeOption = TransactionScopeOption.Required)
{
//TransactionManager.ImplicitDistributedTransactions = true;
var transactionOptions = new TransactionOptions
{
IsolationLevel = IsolationLevel.ReadCommitted,
Timeout = TransactionManager.DefaultTimeout
};
return new TransactionScope(transactionScopeOption, transactionOptions, TransactionScopeAsyncFlowOption.Enabled);
//return new TransactionScope(TransactionScopeOption.Required, TransactionScopeAsyncFlowOption.Enabled);
}
public bool Transaction(Func<TransactionScope, bool> callbackTransactionBody, bool throwException = false)
=> TransactionInner(callbackTransactionBody, throwException);
/// <summary>
/// Using LoskService, global lock!
/// </summary>
/// <param name="callbackTransactionBody"></param>
/// <param name="throwException"></param>
/// <returns></returns>
public bool TransactionSafe(Func<TransactionScope, bool> callbackTransactionBody, bool throwException = false)
{
using (LockService.SemaphoreSlim.UseWait())
{
return TransactionInner(callbackTransactionBody, throwException);
}
}
public Task<bool> TransactionAsync(Func<TransactionScope, Task<bool>> callbackTransactionBody, bool throwException = false)
=> TaskHelper.ToThreadPoolTask(() => TransactionInnerAsync(callbackTransactionBody, throwException));
/// <summary>
/// Using LoskService, global lock!
/// </summary>
/// <param name="callbackTransactionBody"></param>
/// <param name="throwException"></param>
/// <returns></returns>
public Task<bool> TransactionSafeAsync(Func<TransactionScope, Task<bool>> callbackTransactionBody, bool throwException = false)
{
return TaskHelper.ToThreadPoolTask(async () =>
{
using (await LockService.SemaphoreSlim.UseWaitAsync())
{
return await TransactionInnerAsync(callbackTransactionBody, throwException);
}
});
}
private async Task<bool> TransactionInnerAsync(Func<TransactionScope, Task<bool>> callbackTransactionBody, bool throwException = false)
{
bool result;
try
{
using (var transaction = CreateTransactionScope())// new TransactionScope( /*TransactionScopeOption.RequiresNew, */TransactionScopeAsyncFlowOption.Enabled))
{
result = await callbackTransactionBody(transaction);
if (result) transaction.Complete();
}
if (!result) Logger.Warning($"TransactionInnerAsync({this}) transaction ROLLBACK!");
}
catch (Exception ex)
{
if (throwException) throw;
result = false;
Logger.Error($"TransactionInnerAsync({this}) transaction ROLLBACK! ex: {ex.Message}{AcEnv.NL}", ex);
}
return result;
}
private bool TransactionInner(Func<TransactionScope, bool> callbackTransactionBody, bool throwException = false)
{
bool result;
try
{
using(var transaction = CreateTransactionScope()) //new TransactionScope( /*TransactionScopeOption.RequiresNew, */TransactionScopeAsyncFlowOption.Enabled)
{
result = callbackTransactionBody(transaction);
if (result) transaction.Complete();
}
if (!result) Logger.Warning($"TransactionInner({this}) transaction ROLLBACK!");
}
catch (Exception ex)
{
if (throwException) throw;
result = false;
Logger.Error($"TransactionInnerAsync({this}) transaction error! ex: {ex.Message}{AcEnv.NL}", ex);
}
return result;
}
public override string ToString()
{
return GetType().Name;
}
}