2015-01-04 2 views
2

У меня есть приложение Kendo, использующее Entity Framework для доступа к хранимым процедурам. Существует транзакция, используемая при вызове хранимых процедур. Но он дает,Почему транзакция сбой в Entity Framework

Операция транзакции не может быть выполнена, так как ожидаются запросы, обрабатывающие эту транзакцию.

код выглядит следующим образом,

FlightCenterEntities _repository = new FlightCenterEntities(connectionString); 
    ... 
    using (TransactionScope scope = new TransactionScope()) 
    { 
     this._repository.uspDeleteSalesSupplier(salesId); 

     // Write to Sales table 
     this._repository.uspUpdateSales(
          salesId, 
          userId, 
          shop, 
          createdDateTime, 
          bookingDate, 
          passengerName, 
          destination, 
          deposit, 
          saleLocation 
          ).SingleOrDefault(); 

     for (int i = 0; i < list.Count; i++) 
     { 
      // Write to SalesSupplier table 
      var returnValue = this._repository.uspAddSalesSupplier(
                salesId, 
                list[i].SourceTypeName, 
                list[i].SupplierName, 
                list[i].SaleValue, 
                list[i].NumberPassengers 
                ).SingleOrDefault(); 

      status = returnValue == null ? 0 : (int)returnValue; 
      if (status == 0) 
       break; 
     } 

     scope.Complete(); 

ошибка происходит в scope.Complete(). Хранимые процедуры являются следующие,

CREATE PROCEDURE [dbo].[uspDeleteSalesSupplier] 
    @SalesID int 
    AS 

BEGIN 
    SET NOCOUNT ON 

    BEGIN TRY 

     UPDATE [dbo].[SalesSupplier] 
     SET IsDeleted = 1 
     WHERE SalesID = @SalesID 

     SELECT @@Rowcount 

    END TRY 
    BEGIN CATCH 
     --Standard Error Handling 

     SET  @Error_Num = Error_Number() 
     SET  @Error_Message = Error_Message() 

     RAISERROR(@Error_Message , 16, 1, @Procedure_Name) WITH NOWAIT, SETERROR  
    END CATCH; 
END 

CREATE PROCEDURE [dbo].[uspUpdateSales] 
    @SalesID   int, 
    @UserID    varchar(50), 
    @Shop    varchar(50), 
    @CreatedDateTime Datetime, 
    @BookingDate  Datetime, 
    @PassengerName  varchar(50), 
    @Destination  varchar(50), 
    @Deposit   decimal, 
    @SaleLocation  varchar(50) 
    AS 

BEGIN 
    SET NOCOUNT ON 

    BEGIN TRY 

     Update [dbo].[Sales] 
      Set  UserID = @UserID, 
        Shop = @Shop, 
        CreatedDateTime = @CreatedDateTime, 
        BookingDate [email protected], 
        PassengerName = @PassengerName, 
        Destination = @Destination, 
        Deposit = @Deposit, 
        SaleLocation = @SaleLocation 
      Where SalesID = @SalesID  

     SELECT @@Rowcount 

    END TRY 
    BEGIN CATCH 
     --Standard Error Handling 

     SET  @Error_Num = Error_Number() 
     SET  @Error_Message = Error_Message() 

     RAISERROR(@Error_Message , 16, 1, @Procedure_Name) WITH NOWAIT, SETERROR 
    END CATCH; 
END 

CREATE PROCEDURE [dbo].[uspAddSalesSupplier] 
    @SalesID   int, 
    @SourceType   varchar(50), 
    @Supplier   varchar(50), 
    @SaleValue   decimal, 
    @Passengers   int 
    AS 

BEGIN 
    SET NOCOUNT ON 

    BEGIN TRY 

     INSERT INTO [dbo].[SalesSupplier] 
        (SalesID, 
        SourceType, 
        Supplier, 
        SaleValue, 
        Passengers, 
        IsDeleted 
        ) 
      VALUES 
        (@SalesID, 
        @SourceType, 
        @Supplier, 
        @SaleValue, 
        @Passengers, 
        0 
        ) 

     SELECT cast(@@rowcount as int) 

    END TRY 
    BEGIN CATCH 
     --Standard Error Handling 

     SET  @Error_Num = Error_Number() 
     SET  @Error_Message = Error_Message() 

     RAISERROR(@Error_Message , 16, 1, @Procedure_Name) WITH NOWAIT, SETERROR 
    END CATCH; 
END 
+0

Возможно, вы делаете другие обновления репозитория в '...'? Предложите «SaveChanges()» перед тем, как начать транзакцию вокруг ваших SPROC, или иначе, создайте новый DbContext внутри TransactionScope только для использования вашими вызовами SPROC. – StuartLC

+0

Существует еще одна область транзакций с использованием нескольких Insert into и без проблем. Похоже, всякий раз, когда в области видится 2 или более обновлений, это приведет к ошибке. Как создать новый DbContext внутри области транзакций? Вы можете опубликовать его как ответ, чтобы получить кредит. – user585440

ответ

3

Редактировать

Похоже, что этот issue here.

Чтобы обойти эту проблема, чтобы оценить возвращаемый результат всех импортированные хранящихся проков через .FirstOrDefault() или SingleOrDefault(), как вы сделали с двумя другими процедурами, например:

var foo = this._repository.uspDeleteSalesSupplier(salesId).FirstOrDefault(); 

Оригиналом ответ (не полезно)

Возможно, вы делаете другие обновления репозитория в разделе с пометкой ...?

Если есть другие отложенные обновления на хранилище, вам нужно будет промыть их с помощью SaveChanges(), прежде чем начать транзакцию вокруг SPROCs на тот же DbContext

С другой стороны, создать новый DbContext внутри TransactionScope только для использования вашего SPROC звонков следующим образом:

using (var scope = new TransactionScope(
    TransactionScopeOption.RequiresNew, 
    new TransactionOptions 
    { 
     IsolationLevel.ReadCommitted 
    })) 
{ 
    var sprocRepository = new FlightCenterEntities(connectionString); 
    sprocRepository.uspDeleteSalesSupplier(salesId); 
    ... replace the this._repository with sprocRepository for the other usp calls. 

    scope.Complete(); 
} 

Предполагая, что вы не требуете вложенной TransactionScope, я добавил явные TransactionScopeOption.RequiresNew, а также reduced изоляцию в ReadCommitted.

+0

В этом разделе нет других обновлений репозитория. sprocRepository существует только в новом TransactionScope, верно? – user585440

+0

Просы фактически не компилируются, например. переменные '@ Error' не объявляются. Возможно, есть еще некорректный «BEGIN TRAN», скрытый в PROC где-то? – StuartLC

+0

Я попытался создать новый DbContext, например sprocRepository, но все равно не смог с той же ошибкой. – user585440

Смежные вопросы