diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Uow/MongoDB/UnitOfWorkMongoDbContextProvider.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Uow/MongoDB/UnitOfWorkMongoDbContextProvider.cs index 671a676726..a8743c6e05 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Uow/MongoDB/UnitOfWorkMongoDbContextProvider.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Uow/MongoDB/UnitOfWorkMongoDbContextProvider.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; @@ -7,6 +8,8 @@ using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using MongoDB.Bson; using MongoDB.Driver; +using MongoDB.Driver.Core.Misc; +using MongoDB.Driver.Core.Servers; using Volo.Abp.Data; using Volo.Abp.MongoDB; using Volo.Abp.MultiTenancy; @@ -127,7 +130,7 @@ namespace Volo.Abp.Uow.MongoDB var client = CreateMongoClient(mongoUrl); var database = client.GetDatabase(databaseName); - if (unitOfWork.Options.IsTransactional) + if (unitOfWork.Options.IsTransactional && IsSupportedTransactions(client)) { return CreateDbContextWithTransaction(unitOfWork, mongoUrl, client, database); } @@ -147,7 +150,7 @@ namespace Volo.Abp.Uow.MongoDB var client = CreateMongoClient(mongoUrl); var database = client.GetDatabase(databaseName); - if (unitOfWork.Options.IsTransactional) + if (unitOfWork.Options.IsTransactional && IsSupportedTransactions(client)) { return await CreateDbContextWithTransactionAsync( unitOfWork, @@ -285,5 +288,55 @@ namespace Volo.Abp.Uow.MongoDB { return _cancellationTokenProvider.FallbackToProvider(preferredValue); } + + /// + /// https://github.com/mongodb/mongo-csharp-driver/blob/master/src/MongoDB.Driver.Core/Core/Bindings/CoreSession.cs#L495 + /// + /// + /// + /// + protected virtual bool IsSupportedTransactions(MongoClient client) + { + try + { + var connectedDataBearingServers = client.Cluster.Description.Servers.Where(s => s.State == ServerState.Connected && s.IsDataBearing).ToList(); + + if (connectedDataBearingServers.Count == 0) + { + throw new NotSupportedException("StartTransaction cannot determine if transactions are supported because there are no connected servers."); + } + + foreach (var connectedDataBearingServer in connectedDataBearingServers) + { + var serverType = connectedDataBearingServer.Type; + + switch (serverType) + { + case ServerType.Standalone: + throw new NotSupportedException("Standalone servers do not support transactions."); + case ServerType.ShardRouter: + Feature.ShardedTransactions.ThrowIfNotSupported(connectedDataBearingServer.Version); + break; + case ServerType.LoadBalanced: + // do nothing, load balancing always supports transactions + break; + default: + Feature.Transactions.ThrowIfNotSupported(connectedDataBearingServer.Version); + break; + } + } + } + catch (Exception e) + { + Logger.LogError("The current MongoDB database does not support transactions, " + + "All operations will be performed in non-transactions. " + + "This may cause errors, " + + "Please make your database support transactions."); + Logger.LogException(e); + return false; + } + + return true; + } } }