题
我从事 SQL 工作的时间并不长,但我想我明白,通过将 SQL 语句包装在事务中,所有语句都完成,或者没有一个语句完成。这是我的问题。我有一个包含 lineitem 集合的订单对象。行项目在 order.OrderId 上相关。我已经证实 所有 ID 均已设置且正确 但是当我尝试保存(插入)订单时,我得到了 INSERT 语句与 FOREIGN KEY 约束“FK_OrderItemDetail_Order”冲突。冲突发生在数据库“MyData”、表“dbo.Order”、列“OrderId”中。
伪代码:
create a transaction transaction.Begin() Insert order Insert order.LineItems <-- error occurs here transaction.Commit
实际代码:
... entity.Validate(); if (entity.IsValid) { SetChangedProperties(entity); entity.Install.NagsInstallHours = entity.TotalNagsHours; foreach (OrderItemDetail orderItemDetail in entity.OrderItemDetailCollection) { SetChangedOrderItemDetailProperties(orderItemDetail); } ValidateRequiredProperties(entity); TransactionManager transactionManager = DataRepository.Provider.CreateTransaction(); EntityState originalEntityState = entity.EntityState; try { 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(); } catch { if (transactionManager.IsOpen) { transactionManager.Rollback(); } entity.EntityState = originalEntityState; } } ...
有人建议我需要使用两项交易,一项用于订单,一项用于订单项,但我有理由确信这是错误的。但我已经为此奋斗了一天多了,我需要解决它,这样我就可以继续前进,即使这意味着使用一个糟糕的解决方法。我可能只是做了一些愚蠢的事情吗?
解决方案
我注意到,你说你正在使用NetTiers为您生成代码。
我用NetTiers自己和发现,如果你从表中删除外键约束,其重新添加到同一个表,然后在数据库中可能有助于重新进行更改后再次运行NetTiers构建脚本数据访问层。我已经取得了积极成果试过这种偶尔。
祝您的问题。
其他提示
如果没有看到你的代码,很难说问题是什么。可能有很多事情,但看看这些:
- 这是显而易见的,但是您的两个插入命令位于拥有事务的同一连接上(并且连接始终保持打开状态),对吧?
- 您是否在第一次插入后检索与约束相关的 ID,并在执行命令之前将其写回到第二次插入的数据中?
- 数据库中的约束可能设置错误。
您绝对不想使用两个事务。
看起来对了LineItem INSERT语句中未正确设置该订单的价值..这应该是Insert order
步骤的结果。你有没有(和测试)的单个SQL语句?
我不认为你的问题有什么关系事务控制。
我有这样的经验,但它看起来像你可能已经指定了一个键值所不具备父表。很抱歉,但我不能帮你比这更多。
但问题是你如何处理错误。当错误发生时,交易不会自动回滚。你当然可以(并且可能应该)选择要做到这一点,但是这取决于你的应用程序或你在哪里,你可能还是想提交。在这种情况下,这正是你在做什么。你需要用一些错误处理代码周围还有回滚代码时发生错误。
在错误看起来未报错了LineItem适当的 FK的OrderId 强>这是由为了将顺序表的插入自动生成。你说你已经检查了IDS,你必须在订单详情检查FKS呢?