SQL事务如何工作?

我没有在SQL工作太久,但我认为我理解通过在事务中包装SQL语句,所有语句都已完成,或者没有完成。 这是我的问题。 我有一个具有lineitem集合的订单对象。 订单项与订单相关。订单号。 我已经validation所有的ID都已设置并且是正确的,但是当我尝试保存(插入)我得到的顺序时,INSERT语句与FOREIGN KEY约束“FK_OrderItemDetail_Order”冲突。 冲突发生在数据库“MyData”,表“dbo.Order”,列’OrderId’中。

伪代码:

创建一个事务transaction.Begin()插入命令Insert order.LineItems < - 这里发生错误transaction.Commit 

实际代码:

 ...
 entity.Validate();
 if(entity.IsValid)
 {
     SetChangedProperties(实体);
     entity.Install.NagsInstallHours = entity.TotalNagsHours;
     foreach(在entity.OrderItemDetailCollection中的OrderItemDetail orderItemDetail)
     {
         SetChangedOrderItemDetailProperties(orderItemDetail);
     }
     ValidateRequiredProperties(实体);
     TransactionManager transactionManager = DataRepository.Provider.CreateTransaction();
     EntityState originalEntityState = entity.EntityState;
    尝试
     {
         entity.OrderVehicle.OrderId = entity.OrderId;
         entity.Install.OrderId = entity.OrderId;
         transactionManager.BeginTransaction();

         SaveInsuranceInformation(transactionManager,entity);
         DataRepository.OrderProvider.Save(transactionManager,entity);
         DataRepository.OrderItemDetailProvider.Save(transactionManager,entity.OrderItemDetailCollection);  if(!entity.OrderVehicle.IsEmpty)
         {
             DataRepository.OrderVehicleProvider.Save(transactionManager,entity.OrderVehicle);
         }
         transactionManager.Commit();
     }
    抓住
     {
         if(transactionManager.IsOpen)
         {
             transactionManager.Rollback();
         }
         entity.EntityState = originalEntityState;
     }
 }
 ...

有人建议我需要使用两个交易,一个用于订单,一个用于订单项,但我有理由相信这是错误的。 但是我已经打了一天这一天了,我需要解决它,所以我可以继续前进,即使这意味着使用糟糕的工作。 我可能只是在做一些愚蠢的事情吗?

我注意到你说你使用NetTiers进行代码生成。

我自己使用过NetTiers,并且发现如果从表中删除外键约束,将其添加回同一个表,然后在数据库中进行更改后再次运行NetTiers的构建脚本可能有助于重置数据访问层。 我偶尔尝试过这种方法并取得了积极成果。

祝你好运。

没有看到你的代码,很难说出问题所在。 它可以是任何数量的东西,但看看这些:

  1. 这是显而易见的,但是你的两个插入命令是在同一个连接上(并且连接始终保持打开状态)拥有该事务的权利?
  2. 您是在第一次插入后检索与约束相关的ID,并在执行命令之前将其写回第二次插入的数据中吗?
  3. 可以在DB中设置错误约束。

你绝对不想使用两个交易。

看起来你的lineItems的insert语句没有正确设置订单的值..这应该是Insert order步骤的结果。 您是否查看(并测试过)各个SQL语句?

我不认为你的问题与交易控制有关。

我对此没有任何经验,但看起来您可能已经指定了父表中不可用的键值。 对不起,但我不能帮助你。

问题是你如何处理错误。 发生错误时,不会自动回滚事务。 您当然可以(也可能应该)选择这样做,但根据您的应用程序或您所在的位置,您可能仍然希望提交它。 在这种情况下,这正是你正在做的事情。 您需要在那里包装一些error handling代码,以便在发生错误时回滚代码。

该错误看起来没有为LineItem提供正确的FK OrderId ,该订单是通过将订单插入订单表而自动生成的。 你说你已经检查了ID,你是否也检查了订单详情中的FK?

Interesting Posts