Krishan
Krishan

Reputation: 169

How to use TransactionScope in Entity Framework

I am developing student marking system using ASP.NET MVC and Entity Framework. There is a heavy method I am using for calculate marking. At a given time there are about 50 users enter marks to system and that heavy method call by all the users. It gives me deadlock most of the time. I am using a TransactionScope.

This is my code:

try
{
    using (context = new SIMSDBAPPEntities())
    {
        using (TransactionScope scope = new TransactionScope())
        {
              // My heavy calculation
        } 

        scope.Complete();
        context.SaveChanges();           
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

My heavy method is running inside a TransactionScope. I want to know whether my code has any problems? If yes, what can I do to avoid deadlock situation?

Upvotes: 1

Views: 4449

Answers (3)

hvojdani
hvojdani

Reputation: 470

If you are using just one context for saving data. You dont need to use TransactionScope. when you call SaveChanges Ef automatically enlist all changes and apply them on single transaction. For distributed transactions must use TransactionScope.

[link]Using Transactions or SaveChanges(false) and AcceptAllChanges()?

https://coderwall.com/p/jnniww/why-you-shouldn-t-use-entity-framework-with-transactions

Upvotes: 2

MutantNinjaCodeMonkey
MutantNinjaCodeMonkey

Reputation: 1249

The only way to avoid a deadlock is to access and update records in the same table order every time for every operation that does an update.

This can be very tricky to accomplish in ORMs like EF and nHibernate because the concept of table operations is hidden behind the implementation. You're at the mercy of whatever strategy the framework decides. To work around it, you'd have to be careful to update objects individually and save your changes on a per-object basis. You'd also have to make sure you always save these objects in the same order for every operation that does an update.

What I've done in the past to minimize this issue is to enable the database for isolated snapshots, and use that method for your transaction scope.

https://msdn.microsoft.com/en-us/library/tcbchxcb(v=vs.110).aspx

There are some things that can go wrong here as well (such as writing back to a stale record). But I've found it happens less often than deadlocks.

I found this article helpful too (and gives examples of snapshot isolation).. http://blogs.msdn.com/b/diego/archive/2012/04/01/tips-to-avoid-deadlocks-in-entity-framework-applications.aspx

Upvotes: 0

Stephen Brickner
Stephen Brickner

Reputation: 2602

Consider using an async method to do the heavy calculating.

using (var transaction = Database.BeginTransaction())
{
    try
    {
        var heavyCalulation = await heavyCalulationMethodAsync();
        await context.SaveChangesAsync();
    }
    catch
    {
        transaction.Rollback();
    }
}

Upvotes: 0

Related Questions