Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

new transaction is not allowed because there are other threads running in the session #10282

Closed
nj-sketch opened this issue Nov 14, 2017 · 9 comments

Comments

@nj-sketch
Copy link

nj-sketch commented Nov 14, 2017

I am getting this error even though I am using asynchronous methods.

Here is the code where I am calling the method. I am getting error when I am trying to save Resource entity.

                    {
                        CultureId = resource.CultureId,
                        ResourceCategoryId = resource.ResourceCategoryId,
                        Key = resource.Key.Trim(),
                        Value = resource.Value.Trim(),
                        CreatedDate = DateTime.UtcNow,
                        LastUpdated = DateTime.UtcNow
                    };

                    await _resourceService.Add(newResource);
                    await _unitOfWork.SaveAsync();

                    var oldResource = new Resource(); 
                    var resourceAuditLogModel = new AuditLogModel
                    {
                        AuditActionType = AuditActionType.Create,
                        KeyField =  newResource.Id.ToString(),
                        OldObject = oldResource,
                        NewObject = newResource,
                        LoggedUserEmail = loggedUser.Email,
                        ComparisonType = ComparisonType.ObjectCompare
                    };
                    await _auditLogService.Add(resourceAuditLogModel);
                    await _unitOfWork.SaveAsync();

Here is the how I have SaveAsync() method

public async Task SaveAsync()
        {
            try
            {
                _transaction = _baseContext.Database.BeginTransaction();
                await _baseContext.SaveChangesAsync();
                _transaction.Commit();
            }
            catch (Exception ex)
            {
                _transaction.Rollback();
                throw;
            }
            finally
            {
                _transaction.Dispose();
            }
        }

So, what happens is the error doesn't occur on record for first. But It occurs in next time when we save the new record.

Here is the screenshot of the stack trace.
http://prntscr.com/ha8fwx

Further technical details

EF Core version: 2.0
Database Provider: (Microsoft.EntityFrameworkCore.SqlServer)
Operating system:
IDE: (e.g. Visual Studio 2017)

@anpete
Copy link
Contributor

anpete commented Nov 14, 2017

@supernarwen Can you post the full stack trace as well? How is _baseContext being scoped. Is it possible that it is being shared by different threads?

@nj-sketch
Copy link
Author

nj-sketch commented Nov 15, 2017

Here is the full stack trace of the error.

at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
 at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
 at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
 at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
 at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
 at System.Data.SqlClient.TdsParser.TdsExecuteTransactionManagerRequest(Byte[] buffer, TransactionManagerRequestType request, String transactionName, TransactionManagerIsolationLevel isoLevel, Int32 timeout, SqlInternalTransaction transaction, TdsParserStateObject stateObj)
 at System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransactionYukon(TransactionRequest transactionRequest, String transactionName, IsolationLevel iso, SqlInternalTransaction internalTransaction)
 at System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransaction(TransactionRequest transactionRequest, String name, IsolationLevel iso, SqlInternalTransaction internalTransaction)
 at System.Data.SqlClient.SqlInternalConnection.BeginSqlTransaction(IsolationLevel iso, String transactionName, Boolean shouldReconnect)
 at System.Data.SqlClient.SqlConnection.BeginTransaction(IsolationLevel iso, String transactionName)
 at System.Data.SqlClient.SqlConnection.BeginDbTransaction(IsolationLevel isolationLevel)
 at System.Data.Common.DbConnection.BeginTransaction(IsolationLevel isolationLevel)
 at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.BeginTransactionWithNoPreconditions(IsolationLevel isolationLevel)
 at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.<BeginTransactionAsync>d__28.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
 at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
 at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
 at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.<BeginTransactionAsync>d__26.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
 at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
 at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
 at Lumle.Data.Data.UnitOfWork.<SaveAsync>d__4.MoveNext() in C:\Users\ekbana-niraj\Documents\Visual Studio 2017\Projects\lumle\Infrastructures\Lumle.Data\Data\UnitOfWork.cs:line 41

Here is how I have registered my baseContext

services.AddScoped(typeof(BaseContext));

Is it because I have not implemented IDisposable in my UnitofWork?

And here is how my repositories are injected in DI. I am using https://github.com/autofac/Autofac.Extensions.DependencyInjection for DI purpose

  public static IServiceProvider Build(this IServiceCollection services,
            IConfiguration configuration, IHostingEnvironment hostingEnvironment)
        {
            var builder = new ContainerBuilder();
            builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>));

@ajcvickers
Copy link
Member

@supernarwen It's certainly the case that you need to dispose the DbContext properly. Beyond that, the context is not thread safe, nor are the underlying ADO.NET objects like DbConnection. Can you check that you don't have multiple threads accessing these thing concurrently? If after that you're still seeing an issue, then please post a complete code listing or project that reproduces that issue.

@ajcvickers
Copy link
Member

EF Team Triage: Closing this issue as the requested additional details have not been provided and we have been unable to reproduce it.

BTW this is a canned response and may have info or details that do not directly apply to this particular issue. While we'd like to spend the time to uniquely address every incoming issue, we get a lot traffic on the EF projects and that is not practical. To ensure we maximize the time we have to work on fixing bugs, implementing new features, etc. we use canned responses for common triage decisions.

@luigi68
Copy link

luigi68 commented Feb 26, 2018

Hi,
I am experiencing same issue with EF Core 2.0 (dbProvider:Microsoft.EntityFrameworkCore.SqlServer) , the same code perfectly works using EF 6.2.
I am pretty sure that i don't have multiple threads accessing Context or Connection.
Can you give me some hints?

Regards
Luigi

@ajcvickers
Copy link
Member

@luigi68 Please file a new issue including a runnable project/solution or complete code listing that demonstrates the behavior you are seeing.

@shaher
Copy link

shaher commented Jul 4, 2018

I have the same problem after upgrading to EF Core 2.1, at least for now in two different places in the code, the same code was running with no problems before upgrade from 2.0

The issue seems to be related to union, after changing the code as below the error disappeared.
In BOTH places the problem fixed by dividing the union to multi selects and do union in memory.

This code failed

var uids = _db.Table1.Where(x => x.AccountUId == accountUId).Select(x => x.UId)
    .Union(_db.Table2.Where(x => x.AccountUId == accountUId).Select(x => x.UId))
    .ToList();

This code succeeded

var uids1 = _db.Table1.Where(x => x.AccountUId == accountUId).Select(x => x.UId).ToList();
var uids2 = _db.Table2.Where(x => x.AccountUId == accountUId).Select(x => x.UId).ToList();
var uids = uids1.Union(uids2);  //UNION in memeory

But now there is an extra database request!
It seems EF stuck with other internal selects in the union!
Note:
I was getting the Exception later in SaveChanges. In Sql profiler, SaveChanges was not running any Sql command, but after the error, I saw the "stuck" Select in Sql profiler.

I opened a new issue in thread #12549

@AJLC
Copy link

AJLC commented Nov 30, 2018

Hi. I had the same issue and fixed the problem as per shaher's solution. i.e. two separate reads then union the result.

@linehammer
Copy link

This exception is due to Entity Framework creating an implicit transaction during the SaveChanges() call. Invoking C# SaveChanges() method begins a transaction which automatically rolls back all changes persisted to the database if an exception occurs before iteration completes; otherwise the transaction commits . The best way to work around the error is to use a different pattern (i.e., not saving while in the midst of reading) or by explicitly declaring a transaction.

@ajcvickers ajcvickers reopened this Oct 16, 2022
@ajcvickers ajcvickers closed this as not planned Won't fix, can't repro, duplicate, stale Oct 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants