yo chauhan
yo chauhan

Reputation: 12295

Transaction Deadlock and DBContext

Hi i am using Entity Framework 4.1 code first approach . I have class MyContainer that inherits DBContext .

I have a process that has 7 steps each step accesses many repository methods (about 60) .This process executes automatically or mannually depends upon business logic and user requirement . Now for performance point of view for automatic process i created context i.e object of MyContainer once and pass it to all methods and dispose it at the end of process and its working fine and improved the performance.But when this process is executed mannually same methods are executed and container is created and disposed in the method itself. eg below but it is just rough code.

public bool UpdateProcess(Process process, MyContainer container = null)
    {
        bool disposeContainer = false;
        if (container == null)
        {
            container = new MyContainer();
            disposeContainer = true;
        }
        var result = SaveProcess(container, process);
        container.SaveChanges();
        if (disposeContainer)
            container.Dispose();
        return result;
    }

For Automatic Process transaction is created at the beginning of the process and ended at the end of the process and for manual transaction is created at the bll in the method which is called according to the user action on ui.Now suppose my automatic process is running and simultaneously user did some action on ui I gets the Exception "Transaction (Process ID 65) Was Deadlocked On Lock Resources With Another Process And Has Been Chosen" When the UpdateProcess() method is called together from both mannual and automatic process, I get it on container.SaveChanges().

Any help will be highly appreciated.

If i create a transaction scope in this repository method like

public bool UpdateProcess(Process process, MyContainer container = null)
 {         bool disposeContainer = false;        
           if (container == null)  
           {             
                  container = new MyContainer();         
                  disposeContainer = true;         
            }
       using(var trans=new TransactionScop(TransactionScopeOption.RequiresNew))        
       { 
          var result = SaveProcess(container, process);
          container.SaveChanges();
          trans.Complete();
       }        
          if (disposeContainer)           
          container.Dispose();        
          return result;   
 } 

It works fine. However I dont want to create the transaction in repository as the transactions been already made in bll.

Any help will be appericiated.

Upvotes: 3

Views: 2504

Answers (1)

Johnv2020
Johnv2020

Reputation: 2136

The issue (sql deadlocking) you are having is common to most non-trivial client - database systems and can be very difficult to resolve.

The primary rule in designing code where deadlocks may occur is to assume that they will and design the application to handle them appropriately. This is normally handled via resubmitting the transaction. As documented by microsoft here

Although deadlocks can be minimized, they cannot be completely avoided. That is why the front-end application should be designed to handle deadlocks.

In order to minimise any deadlocks you are seeing the normal approach I take is as follows:

  1. Run profiler with a deadlock graph enabled to capture all deadlocks
  2. Export all deadlocks to text and investigate why they are occurring
  3. Check to see these can be minimised by using table hints and/or reducing the transation isolation level
  4. See if they can be minimised by other means, e.g. changing the order of operation
  5. Finally after all this has been completed ensure that you are trapping for deadlocks anytime you communicate with the database & resubmit the transaction / query etc.

Upvotes: 2

Related Questions