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的构建脚本可能有助于重置数据访问层。 我偶尔尝试过这种方法并取得了积极成果。
祝你好运。
没有看到你的代码,很难说出问题所在。 它可以是任何数量的东西,但看看这些:
- 这是显而易见的,但是你的两个插入命令是在同一个连接上(并且连接始终保持打开状态)拥有该事务的权利?
- 您是在第一次插入后检索与约束相关的ID,并在执行命令之前将其写回第二次插入的数据中吗?
- 可以在DB中设置错误约束。
你绝对不想使用两个交易。
看起来你的lineItems的insert语句没有正确设置订单的值..这应该是Insert order
步骤的结果。 您是否查看(并测试过)各个SQL语句?
我不认为你的问题与交易控制有关。
我对此没有任何经验,但看起来您可能已经指定了父表中不可用的键值。 对不起,但我不能帮助你。
问题是你如何处理错误。 发生错误时,不会自动回滚事务。 您当然可以(也可能应该)选择这样做,但根据您的应用程序或您所在的位置,您可能仍然希望提交它。 在这种情况下,这正是你正在做的事情。 您需要在那里包装一些error handling代码,以便在发生错误时回滚代码。
该错误看起来没有为LineItem提供正确的FK OrderId ,该订单是通过将订单插入订单表而自动生成的。 你说你已经检查了ID,你是否也检查了订单详情中的FK?