Base solution for your next web application
Open Closed

Reading from one context within another #2391


User avatar
0
vnetonline created

Hi

There are two contexts in my application, one is the standard context and the other the database first context which talks to another database.

Normal context public class NormalContext : AbpZeroDbContext<Tenant, Role, User>

and Database first context

public class MyDbContext : AbpDbContext

I need to fetch some information from NormalContext within the MyDbContext. I am currently using the following function in MyDbContext

    private string GetUserName(long? userId)
    {
        if (userId == null)
            return null;
        using (var context = LocalIocManager.Resolve&lt;NormalContext &gt;())
        {
            var user = context.Users.Find(userId);
            return user.Name;
        }
    }

However this throws an exception

nHandling.AbpApiExceptionFilterAttribute - The underlying provider failed on Open. System.Data.Entity.Core.EntityException: The underlying provider failed on Open. ---> System.Transactions.TransactionAbortedException: The transaction has aborted. ---> System.Transactions.TransactionPromotionException: Failure while attempting to promote transaction. ---> System.Data.SqlClient.SqlException: MSDTC on server 'PC120' is unavailable.

PC120 is the local server that hosts the database for the NormalContext .

I dont know if I am resolving the NormalContext in the right manner.

Any help would be appreciated here.


5 Answer(s)
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Since you want to connect to a different database, you need to enable MSDTC (Distributed Transaction Coordinator windows service) on both database server and your local machine (or the server your web app runs).

    In this way, you can get data from your second dbContext.

    Second alternative, you can use DbContextEfTransactionStrategy. To use it, please read Transaction Management section of this document <a class="postlink" href="http://aspnetboilerplate.com/Pages/Documents/EntityFramework-Integration#transaction-management">http://aspnetboilerplate.com/Pages/Docu ... management</a>.

  • User Avatar
    0
    vnetonline created

    Thank you for your prompt reply as always.

    After setting the MSDTC (Distributed Transaction Coordinator windows service) to be enabled on both the database server and the web server, I get the following error

    The underlying provider failed on Commit. System.Data.Entity.Core.EntityException: The underlying provider failed on Commit. ---> System.ArgumentNullException: Value cannot be null. Parameter name: connection

    I was thinking on giving up on this approach and instead use the sessions object to pass the value. Hence any documentation on custom session objects would be very helpful. When I googled this, I got the link below, but would appreciate it if you can refer me to the correct github repository for adding claims to sessions.

    #41@d7ff85a3-fbf9-44f1-ab2c-2d3de54aec24

    Thanks

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    I haven't seen this error before, if you choose to continue on that way, we can investiagate it. Otherwise, you can tahe a look at custom session implementation here <a class="postlink" href="https://gist.github.com/hikalkan/67469e05475c2d18cb88">https://gist.github.com/hikalkan/67469e05475c2d18cb88</a>.

    Please write back if this is not what you are looking for.

  • User Avatar
    0
    vnetonline created

    Thank you for your response, although in the custom session implementation, the break point does not hit SignInAsync(User user, ClaimsIdentity identity = null, bool rememberMe = false) . However I investigated further to find out that the username does get populated in the claims object which can be retrieved simply by doing a var cp = claimsPrincipal.Claims.FirstOrDefault(c => c.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name");

    Since it is this simple to get a username and the fact that it is highly unlikely that we will need to get any objects from the other context within this context's core functions, this solution will do. I guess the problem was accessing the other context within the methods of this context which is not a good practice in either case. In normal scenario, I would be using repositories.

    Thanks though as your response directed me to the correct solution.

  • User Avatar
    0
    ismcagdas created
    Support Team

    I'm glad that you have managed it :).