Base solution for your next web application
Open Closed

transaction is not associated with the current connection #4162


User avatar
0
fguo created

I am using (core+angular) v4.5.1, and need to add a service for creating a record into database table. The service works fine until I insert the current username into the record.

I am using two database with separated DbContext. I need to get the username by GetCurrentUser().UserName from DbContext1 and insert the username into an entity in DbContext2. It seems not allowed this operation, and throw out an exception:

Mvc.ExceptionHandling.AbpExceptionFilter - The specified transaction is not associated with the current connection. Only transactions associated with the current connection may be used.

I searched it on forum and found a similar issue on "2 Context - Transaction Error #372". It seems saying the issue solved on "the milestones: v4.4, v4.5 on Aug 25 ". I wonder if my above issue is new? If so, can you give a clue for a workaround?

Thanks,


12 Answer(s)
  • User Avatar
    0
    aaron created
    Support Team

    Switch to DbContext transaction API in PreInitialize method of YourEntityFrameworkModule:

    Configuration.ReplaceService<IEfCoreTransactionStrategy, DbContextEfCoreTransactionStrategy>(DependencyLifeStyle.Transient);
    
  • User Avatar
    0
    fguo created

    Thank you for your prompt response!

    I am trying to add that line into PreInitialize method of EntityFrameworkCoreModule, with 2 namespaces: using Abp.EntityFrameWorkCore.Uow; using Abp.Dependency;

    but got a compile error: The non-generic method 'IAbpStartupConfiguration.ReplaceService(Type, Action)' cannot be used with type arguments.

    What did I miss?

  • User Avatar
    0
    aaron created
    Support Team

    Add this namespace:

    using Abp.Configuration.Startup;
    
  • User Avatar
    0
    fguo created

    Just added this namespace, and passed compile, but unfortunately, it still throws the same exception.

    Any idea?

  • User Avatar
    0
    aaron created
    Support Team

    Have you added both DbContexts like in this comment: https://github.com/aspnetzero/aspnet-zero-core/issues/372#issuecomment-327497309

  • User Avatar
    0
    fguo created

    Yes. My both DbContexts work fine, if use them separately. For example, I can get "accessToken" from /api/TokenAuth/Authenticate. The user entity is in ProjectDbContext. I can get "myEntity" from CustomDbContext.

    There seems no built-in way to add multiple DbContexts for multiple databases so far. I tried the way your indicated, but it does not work for me. My CustomDbContext never connected in that way. I know I must miss something. I am still waiting for an "official" release for using multiple DbContext.

    Currently, I use my own workaround. I made an "AppEntityFrameworkCoreModule" which is very similar to "ProjectEntityFrameworkCoreModule", but with different connection string. I added "typeof(App1EntityFrameworkCoreModule)" on the top of WebCoreModule, so both DbContexts can be initialized. They work fine until the issue I met today.

    Here is my problem code for inserting a record into the table in the 2nd database. The "Obj" is an entity in the 2nd DbContext.

        public async Task CreateObj(ObjListDto input)
        {
            var obj = ObjectMapper.Map&lt;Obj&gt;(input);
            obj.Username = GetCurrentUser().UserName; //this line caused the exception
            
            await _objRepository.InsertAsync(obj);
        }
    

    Any idea?

  • User Avatar
    0
    aaron created
    Support Team

    Pass in the proper connection string to UseSqlServer.

    You know it's solved, but you refuse to use the solution?

  • User Avatar
    0
    fguo created

    Pass in the proper connection string to UseSqlServer.

    I even tried to hard-coded the connection strings, but still got SAME exception.

    You know it's solved, but you refuse to use the solution?

    I tried this "solution", but still got SAME exception.

    Let me change an angle to state my question. I want to get the current username while inserting a record into the 2nd database. My following code throws exception:

    public async Task CreateObj(ObjListDto input) { var obj = ObjectMapper.Map<Obj>(input); obj.Username = GetCurrentUser().UserName; //this line caused the exception await _objRepository.InsertAsync(obj); }

    Can you give me another way to get the current username ?

    Thanks,

  • User Avatar
    0
    aaron created
    Support Team

    Try this:

    public async Task CreateObj(ObjListDto input)
    {
        string username;
        using (var uow = _unitOfWorkManager.Begin(TransactionScopeOption.Suppress)
        {
            username = GetCurrentUser().UserName;
            uow.Complete();
        }
        var obj = ObjectMapper.Map<Obj>(input);
        obj.Username = username;
        await _objRepository.InsertAsync(obj);
    }
    
  • User Avatar
    0
    fguo created

    Great!!! It works and solved my issue. :o

    Thank you very much!

  • User Avatar
    0
    fguo created

    The above aaron's code works fine in my methods. Now I have multiple methods (createObj, updateObj, GetObj, and so on) which need the same username, so I moved the same code into the service class constructor. The "GetCurrentUser().UserName;" always throw out exception: Invalid object name 'AbpUsers'.

    What do I miss?

    Thanks,

  • User Avatar
    0
    aaron created
    Support Team

    Don't do it in the constructor. You can make it a method.