O registro é criado no banco de dados se a transação for abortada (MongoDB.Driver e .NETCore)
Alguém tentou usar transações no .NetCore? Eu tentei e não consigo fazê-lo funcionar corretamente.
Minha configuração:
Mongo4 (conjunto de réplicas de 3 nós)Visual Studio 2017MongoDB.Driver 2.7.0.Net Core 2.0. Aplicação de consoleEstou seguindo as instruções:https://docs.mongodb.com/manual/core/transactions/
O problema é que o novo documento é criado no banco de dados toda vez (se eu abortar uma transação, se eu confirmar uma transação, ...)
Também tentei usar transações diretamente no banco de dados e elas funcionam, também tentei com o NodeJS e elas também funcionam. Talvez haja um erro no driver, não sei o que estou fazendo de errado.
Código:
using System;
using MongoDB.Bson;
using MongoDB.Driver;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
var connString = "mongodb://user:password@localhost:27017";
var client = new MongoClient(connString);
using (var session = client.StartSession())
{
try
{
RunTransactionWithRetry(UpdateEmployeeInfo, client, session);
}
catch (Exception exception)
{
// do something with error
Console.WriteLine($"Non transient exception caught during transaction: ${exception.Message}.");
}
}
}
public static void RunTransactionWithRetry(Action<IMongoClient, IClientSessionHandle> txnFunc, IMongoClient client, IClientSessionHandle session)
{
while (true)
{
try
{
txnFunc(client, session); // performs transaction
break;
}
catch (MongoException exception)
{
// if transient error, retry the whole transaction
if (exception.HasErrorLabel("TransientTransactionError"))
{
Console.WriteLine("TransientTransactionError, retrying transaction.");
continue;
}
else
{
throw;
}
}
}
}
public static void CommitWithRetry(IClientSessionHandle session)
{
while (true)
{
try
{
session.CommitTransaction();
Console.WriteLine("Transaction committed.");
break;
}
catch (MongoException exception)
{
// can retry commit
if (exception.HasErrorLabel("UnknownTransactionCommitResult"))
{
Console.WriteLine("UnknwonTransactionCommiResult, retrying commit operation");
continue;
}
else
{
Console.WriteLine($"Error during commit: {exception.Message}.");
throw;
}
}
}
}
// updates two collections in a transaction
public static void UpdateEmployeeInfo(IMongoClient client, IClientSessionHandle session)
{
var employeesCollection = client.GetDatabase("testdatabase").GetCollection<BsonDocument>("employees");
var eventsCollection = client.GetDatabase("testdatabase").GetCollection<BsonDocument>("events");
session.StartTransaction(new TransactionOptions(
readConcern: ReadConcern.Snapshot,
writeConcern: WriteConcern.WMajority));
try
{
employeesCollection.UpdateOne(
Builders<BsonDocument>.Filter.Eq("employee", 3),
Builders<BsonDocument>.Update.Set("status", "Inactive"));
eventsCollection.InsertOne(
new BsonDocument
{
{ "employee", 3 },
{ "status", new BsonDocument { { "new", "Inactive" }, { "old", "Active" } } }
});
}
catch (Exception exception)
{
Console.WriteLine($"Caught exception during transaction, aborting: {exception.Message}.");
session.AbortTransaction();
throw;
}
//I WANT TO ABORT TRANSACTION - BUT THE RECORD "employee:3...." IS STILL IN DATABASE "events"
session.AbortTransaction();
}
public static void UpdateEmployeeInfoWithTransactionRetry(IMongoClient client)
{
// start a session
using (var session = client.StartSession())
{
try
{
RunTransactionWithRetry(UpdateEmployeeInfo, client, session);
}
catch (Exception exception)
{
// do something with error
Console.WriteLine($"Non transient exception caught during transaction: ${exception.Message}.");
}
}
}
}
}