You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We recently updated to the latest Ninject and Ninject extensions library. We have noticed we are now getting disposed exceptions when using the following generic transaction interceptor.
It appears even though we are running the below in request scope it is still holding onto a previous instance of the EF context and using it to try and start a new transaction. Where previously we were getting a new context instance for each request scope.
/// <summary>
/// Used to mark a method that requires being wrapped in a transaction.
/// </summary>
public class UseTransactionAttribute : InterceptAttribute
{
private readonly IsolationLevel _isolationLevel;
/// <summary>
/// Initializes a new instance of the <see cref="UseTransactionAttribute"/> class.
/// </summary>
public UseTransactionAttribute(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted)
{
_isolationLevel = isolationLevel;
}
/// <summary>
/// Create the interceptor attached to this attribute.
/// </summary>
/// <param name="request">The proxy request being made.</param>
/// <returns>A <see cref="IInterceptor"/> to wrap the method in.</returns>
public override IInterceptor CreateInterceptor(IProxyRequest request)
{
var isolationLevel = new ConstructorArgument("isolationLevel", _isolationLevel);
return request.Kernel.Get<UseTransactionInterceptor>(isolationLevel);
}
}
/// <summary>
/// Transaction method is responsible for wrapping a method in a transaction in a consistent way.
/// </summary>
public class UseTransactionInterceptor : IInterceptor
{
private readonly IObjectContextAdapter _context;
private readonly IsolationLevel _isolationLevel;
/// <summary>
/// Initializes a new instance of the <see cref="UseTransactionInterceptor"/> class.
/// </summary>
public UseTransactionInterceptor(IObjectContextAdapter context, IsolationLevel isolationLevel = IsolationLevel.ReadCommitted)
{
_context = context;
_isolationLevel = isolationLevel;
}
/// <summary>
/// Intercept the method call so it can be wrapped in a transaction. Check if a transaction is active, if it isn't start a new one otherwise do nothing as we are already in one.
/// </summary>
/// <param name="invocation">The invocation we are wrapping a transaction around.</param>
public void Intercept(IInvocation invocation)
{
var database = ((DbContext)_context).Database;
// Don't start another transaction if we are already in one.
if (database.CurrentTransaction != null)
{
invocation.Proceed();
}
else
{
using (var transaction = database.BeginTransaction(_isolationLevel))
{
try
{
invocation.Proceed();
transaction.Commit();
}
catch
{
transaction.Rollback();
throw;
}
}
}
}
}
If we replace the line
var database = ((DbContext)_context).Database;
with:
var t = invocation.Request.Kernel.Get<IObjectContextAdapter>();
var database = ((DbContext)t).Database;
We get the behavior we were getting before. So it appears the interceptor is being cached perhaps? Or is this an expected behavior change?
The text was updated successfully, but these errors were encountered:
Hi There,
We recently updated to the latest Ninject and Ninject extensions library. We have noticed we are now getting disposed exceptions when using the following generic transaction interceptor.
It appears even though we are running the below in request scope it is still holding onto a previous instance of the EF context and using it to try and start a new transaction. Where previously we were getting a new context instance for each request scope.
If we replace the line
with:
We get the behavior we were getting before. So it appears the interceptor is being cached perhaps? Or is this an expected behavior change?
The text was updated successfully, but these errors were encountered: