| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- using Microsoft.Extensions.DependencyInjection;
- using Microsoft.Extensions.Logging;
- using MongoDB.Driver;
- using System;
- using System.Threading;
- using System.Threading.Tasks;
- using Volo.Abp;
- using Volo.Abp.Data;
- using Volo.Abp.MongoDB;
- using Volo.Abp.MultiTenancy;
- using Volo.Abp.Threading;
- using Volo.Abp.Uow;
- namespace Bussiness.MongoDB
- {
- /// <summary>
- /// 自定义MongoDB上下文提供程序,禁用事务支持
- /// 用于解决Standalone MongoDB服务器不支持事务的问题
- /// </summary>
- public class NonTransactionalMongoDbContextProvider<TMongoDbContext> : IMongoDbContextProvider<TMongoDbContext>
- where TMongoDbContext : class, IAbpMongoDbContext
- {
- private readonly IUnitOfWorkManager _unitOfWorkManager;
- private readonly IConnectionStringResolver _connectionStringResolver;
- private readonly ICancellationTokenProvider _cancellationTokenProvider;
- private readonly ICurrentTenant _currentTenant;
- private readonly IServiceProvider _serviceProvider;
- private readonly ILogger<NonTransactionalMongoDbContextProvider<TMongoDbContext>> _logger;
- public NonTransactionalMongoDbContextProvider(
- IUnitOfWorkManager unitOfWorkManager,
- IConnectionStringResolver connectionStringResolver,
- ICancellationTokenProvider cancellationTokenProvider,
- ICurrentTenant currentTenant,
- IServiceProvider serviceProvider,
- ILogger<NonTransactionalMongoDbContextProvider<TMongoDbContext>> logger)
- {
- _unitOfWorkManager = unitOfWorkManager;
- _connectionStringResolver = connectionStringResolver;
- _cancellationTokenProvider = cancellationTokenProvider;
- _currentTenant = currentTenant;
- _serviceProvider = serviceProvider;
- _logger = logger;
- }
- public async Task<TMongoDbContext> GetDbContextAsync(CancellationToken cancellationToken = default)
- {
- var unitOfWork = _unitOfWorkManager.Current;
- if (unitOfWork == null)
- {
- throw new AbpException("A DbContext can only be created inside a unit of work!");
- }
- var targetTenantId = _currentTenant.Id;
- var connectionString = await ResolveConnectionStringAsync(targetTenantId);
- var dbContextKey = $"{typeof(TMongoDbContext).FullName}_{connectionString}";
- var databaseApi = unitOfWork.FindDatabaseApi(dbContextKey);
- if (databaseApi == null)
- {
- // 创建不带事务的数据库API
- databaseApi = new MongoDbDatabaseApi(await CreateDbContextAsync(unitOfWork, connectionString, cancellationToken));
- unitOfWork.AddDatabaseApi(dbContextKey, databaseApi);
- }
- return ((MongoDbDatabaseApi)databaseApi).DbContext.As<TMongoDbContext>();
- }
- [Obsolete("Use GetDbContextAsync method.")]
- public TMongoDbContext GetDbContext()
- {
- return AsyncHelper.RunSync(() => GetDbContextAsync());
- }
- private Task<IAbpMongoDbContext> CreateDbContextAsync(IUnitOfWork unitOfWork, string connectionString, CancellationToken cancellationToken)
- {
- var dbContext = unitOfWork.ServiceProvider.GetRequiredService<TMongoDbContext>();
- var mongoUrl = new MongoUrl(connectionString);
- var databaseName = mongoUrl.DatabaseName;
- if (databaseName.IsNullOrWhiteSpace())
- {
- databaseName = ConnectionStringNameAttribute.GetConnStringName<TMongoDbContext>();
- }
- // 创建MongoDB客户端(不使用事务)
- var client = new MongoClient(mongoUrl);
- var database = client.GetDatabase(databaseName);
- // 初始化DbContext,不传入session(即不使用事务)
- dbContext.ToAbpMongoDbContext().InitializeDatabase(database, client, null);
- _logger.LogDebug("MongoDB context created without transaction support for standalone server.");
- return Task.FromResult<IAbpMongoDbContext>(dbContext);
- }
- private async Task<string> ResolveConnectionStringAsync(Guid? tenantId)
- {
- if (tenantId == _currentTenant.Id)
- {
- return await _connectionStringResolver.ResolveAsync(ConnectionStringNameAttribute.GetConnStringName<TMongoDbContext>());
- }
- using (_currentTenant.Change(tenantId))
- {
- return await _connectionStringResolver.ResolveAsync(ConnectionStringNameAttribute.GetConnStringName<TMongoDbContext>());
- }
- }
- }
- /// <summary>
- /// MongoDB数据库API包装类
- /// </summary>
- public class MongoDbDatabaseApi : IDatabaseApi
- {
- public IAbpMongoDbContext DbContext { get; }
- public MongoDbDatabaseApi(IAbpMongoDbContext dbContext)
- {
- DbContext = dbContext;
- }
- }
- }
|