2015-09-22 16 views
7

Sử dụng Entity Framework 6.0.0, tôi thấy một ngoại lệ khi đóng giao dịch.Trường hợp ngoại lệ khi quay lại giao dịch - kết nối đã đóng?

Chúng tôi đã gặp sự cố với các thay đổi đồng thời đối với bảng, vì vậy tôi đã bao gồm nó trong một giao dịch và bây giờ tôi nhận được ngoại lệ về khôi phục.

Mã:

public LockInfo getSharedLock(string jobid) 
{ 
    using (var myDbContext = new MyDbContext()) 
    { 
     using (var transaction = myDbContext.Database.BeginTransaction()) 
     { 
      try 
      { 
       this.logger.log("Attempting to get shared lock for {0}", jobid); 

       var mylocks = 
        myDbContext.joblocks.Where(j => j.customerid == this.userContext.customerid) 
         .Where(j => j.jobid == jobid) 
         .Where(j => j.operatorid == this.userContext.operatorid); 

       var exclusiveLock = mylocks.FirstOrDefault(
        j => j.lockstatus == LockInfo.LockState.Exclusive); 
       if (exclusiveLock != null) 
       { 
        this.logger.log("{0} already had exclusive lock, ignoring", jobid); 
        return LockInfo.populate(exclusiveLock); 
       } 

       var sharedLock = mylocks.FirstOrDefault(
        j => j.lockstatus == LockInfo.LockState.Shared); 
       if (sharedLock != null) 
       { 
        this.logger.log("{0} already had shared lock, ignoring", jobid)); 
        sharedLock.lockdt = DateTime.Now; 
        myDbContext.SaveChanges(); 

        return LockInfo.populate(sharedLock); 
       } 

       var joblock = new joblock 
       { 
        customerid = this.userContext.customerid, 
        operatorid = this.userContext.operatorid, 
        jobid = jobid, 
        lockstatus = LockInfo.LockState.Shared, 
        sharedLock.lockdt = DateTime.Now 
       }; 

       myDbContext.joblocks.Add(joblock); 
       myDbContext.SaveChanges(); 
       transaction.Commit(); 

       this.logger.log("Obtained shared lock for {0}", jobid); 
       return LockInfo.populate(joblock); 
      } 
      catch (Exception ex) 
      { 
       transaction.Rollback(); 
       this.logger.logException(ex, "Exception in getSharedLock(\"{0}\")", jobid); 
       throw; 
      } 
     } 
    } 
} 

Bạn có thể xem khai thác gỗ, trong đoạn code trên. Chúng tôi cũng đã bật ghi nhật ký trong cơ sở dữ liệu. Theo dõi nhật ký:

=================== 
NORMAL TicketLockController.getLock("AK2015818002WL") 
=================== 
SQL Opened connection at 9/22/2015 2:47:49 PM -05:00 
=================== 
SQL Started transaction at 9/22/2015 2:47:49 PM -05:00 
=================== 
NORMAL Attempting to get shared lock for AK2015818002WL 
=================== 
SQL SELECT TOP (1) [Extent1].[customerid] AS [customerid] 
    ,[Extent1].[jobid] AS [jobid] 
    ,[Extent1].[lockdtdate] AS [lockdtdate] 
    ,[Extent1].[lockdttime] AS [lockdttime] 
    ,[Extent1].[operatorid] AS [operatorid] 
    ,[Extent1].[lockstatus] AS [lockstatus] 
    ,[Extent1].[changes] AS [changes] 
FROM [dbo].[joblock] AS [Extent1] 
WHERE ([Extent1].[customerid] = 'TESTTK') 
    AND ([Extent1].[jobid] = 'AK2015818002WL') 
    AND ([Extent1].[operatorid] = 'ADMIN') 
    AND (N'Exclusive' = [Extent1].[lockstatus]) 
=================== 
SQL SELECT TOP (1) [Extent1].[customerid] AS [customerid] 
    ,[Extent1].[jobid] AS [jobid] 
    ,[Extent1].[lockdtdate] AS [lockdtdate] 
    ,[Extent1].[lockdttime] AS [lockdttime] 
    ,[Extent1].[operatorid] AS [operatorid] 
    ,[Extent1].[lockstatus] AS [lockstatus] 
    ,[Extent1].[changes] AS [changes] 
FROM [dbo].[joblock] AS [Extent1] 
WHERE ([Extent1].[customerid] = 'TESTTK') 
    AND ([Extent1].[jobid] = 'AK2015818002WL') 
    AND ([Extent1].[operatorid] = 'ADMIN') 
    AND (N'Shared' = [Extent1].[lockstatus]) 
=================== 
SQL INSERT [dbo].[joblock] (
    [customerid] 
    ,[jobid] 
    ,[lockdtdate] 
    ,[lockdttime] 
    ,[operatorid] 
    ,[lockstatus] 
    ,[changes] 
    ) 
VALUES (
    @0 
    ,@1 
    ,@2 
    ,@3 
    ,@4 
    ,@5 
    ,NULL 
    ) 
=================== 
SQL Closed connection at 9/22/2015 2:47:50 PM -05:00 
=================== 
EXCEPTION Unhandled exception caught: The underlying provider failed on Rollback. 
=================== 
EXCEPTION Inner Exception: Value cannot be null. 
Parameter name: connection 

Hai lựa chọn thành công, sau đó chèn không thành công vì một lý do nào đó. ném một ngoại lệ, và vì một lý do nào đó kết nối sẽ đóng trước khi Rollback() thực thi.

Bất kỳ ý tưởng nào tôi đang làm sai?

==== Thêm đống dấu vết ====

StackTrace cho ngoại lệ bên ngoài:

at System.Data.Entity.Core.EntityClient.EntityTransaction.Rollback() 
    at korterra.kt_api.Shared.TicketLockWrangler.getSharedLock(String jobid) 
    at korterra.kt_ws.ApiControllers.Shared.TicketLockController.getSharedLock(TicketLockDTO ticketLockDTO) 
    at lambda_method(Closure , Object , Object[]) 
    at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters) 
    at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments) 
    at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken) 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Web.Http.Tracing.ITraceWriterExtensions.<TraceBeginEndAsyncCore>d__18`1.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Web.Http.Tracing.ITraceWriterExtensions.<TraceBeginEndAsyncCore>d__18`1.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Web.Http.Filters.AuthorizationFilterAttribute.<ExecuteAuthorizationFilterAsyncCore>d__2.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Web.Http.Controllers.ExceptionFilterResult.<ExecuteAsync>d__0.MoveNext() 

StackTrace cho ngoại lệ bên trong:

at System.Data.Entity.Utilities.Check.NotNull[T](T value, String parameterName) 
    at System.Data.Entity.Infrastructure.Interception.DbTransactionInterceptionContext.WithConnection(DbConnection connection) 
    at System.Data.Entity.Infrastructure.Interception.DbTransactionDispatcher.Rollback(DbTransaction transaction, DbInterceptionContext interceptionContext) 
    at System.Data.Entity.Core.EntityClient.EntityTransaction.Rollback() 
+0

Đăng ToString ngoại lệ đầy đủ. Nhật ký lỗi của bạn không đủ. – usr

+0

Ngoài ra, bạn không cam kết giao dịch trong nhiều trường hợp. Điều đó thực sự có chủ ý? – usr

+0

Tôi không thể tạo lại yêu cầu này. Đó là thứ hiển thị liên tục trong môi trường QA của chúng tôi. Tôi chưa bao giờ thấy nó trong dev. Thông tin duy nhất tôi có ngoài những gì tôi đã đăng là dấu vết ngăn xếp, điều này đơn giản chỉ ra rằng ngoại lệ xảy ra trong mã tôi đã đăng. –

Trả lời

6

Sau các cuộc thảo luận, tôi bắt đầu đăng nhập ngoại lệ trước khi thử quay lại - và điều đó đã tiết lộ lỗi.

Giao dịch được bế tắc:

Exception in getSharedLock("ticketnumber123456"): An error occurred while updating the entries. See the inner exception for details. 

Inner Exception: An error occurred while updating the entries. See the inner exception for details. 

Inner Exception: Transaction (Process ID 139) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction. 

Từ những gì tôi đang đọc, khi bạn nói với một giao dịch đã được thực hiện một nạn nhân bế tắc, nó đã được cuộn lại. Có lẽ đó là lý do tại sao chúng tôi nhận được một ngoại lệ?

Khắc phục có vẻ là nhận ra khi chúng tôi đã bế tắc và không quay lại hoặc không sử dụng giao dịch và thử lại khi chúng tôi nhận được vi phạm chính.

+0

Bạn không nên gọi Rollback bao giờ trong đoạn mã này. Ngoài ra, đây là lỗi của EF. Nó không nên sụp đổ. Nó sẽ báo cáo lỗi sử dụng API hoặc một cái gì đó sử dụng một ngoại lệ rõ ràng. Bạn có thể mở một vấn đề GitHub tại EF repo cho điều này? – usr

+0

Tôi hiện đang cố gắng không sử dụng giao dịch, nhưng chỉ cần thử lại khi các bản ghi cơ bản đã thay đổi - khóa lạc quan. –

Các vấn đề liên quan