Reputation: 3841
Is there a way to create a nested using in a Disposable
object, so this code:
using (var ctx = new MyEntities())
{
ctx.Connection.Open();
using (var tx = dbContext.Connection.BeginTransaction())
{
// ... do awesome things here
ctx.SaveChanges();
tx.Commit();
}
}
to something like this:
using (var txContext = new TransactionContext())
{
// ... do awesome things here
}
?
Currently I have:
public class TransactionContext : IDisposable
{
private MyEntities DbContext { get; set; }
private DbTransaction Transaction { get; set; }
public TransactionContext()
{
DbContext = new MyEntities();
DbContext.Connection.Open();
Transaction = DbContext.Connection.BeginTransaction();
}
void IDisposable.Dispose()
{
try
{
DbContext.SaveChanges();
Transaction.Commit();
}
catch (Exception exception)
{
Transaction.Rollback();
DbContext.Dispose();
}
}
}
I'm not sure if this is correct in ways of disposing the different Disposables
, especially in case of an error/exception.
Upvotes: 2
Views: 109
Reputation: 32276
It would probably be better to use a method instead of a class for this.
private static void RunInTransaction(Action<MyEntities, DbTransaction> action)
{
using (var ctx = new MyEntities())
{
ctx.Connection.Open();
using (var tx = ctx.Connection.BeginTransaction())
{
action(ctx, tx);
ctx.SaveChanges();
tx.Commit();
}
}
}
Then you can call it like this.
RunInTransaction((ctx,tx) =>
{
// ... do awesome things here
});
You can also create a version of this that returns a value
private static T RunInTransactionAndReturn<T>(
Func<MyEntities, DbTransaction, T> function)
{
using (var ctx = new MyEntities())
{
ctx.Connection.Open();
using (var tx = ctx.Connection.BeginTransaction())
{
var result = function(ctx, tx);
ctx.SaveChanges();
tx.Commit();
return result;
}
}
}
Then you can call it like this.
var result = RunInTransactionAndReturn((ctx,tx) =>
{
// ... do awesome things here
return someResult;
});
Upvotes: 2