【发布时间】:2009-11-03 15:46:16
【问题描述】:
我在 SQL 中工作的时间不长,但我认为我理解通过将 SQL 语句包装在事务中,所有语句都完成了,或者没有一个语句完成。这是我的问题。我有一个包含 lineitem 集合的订单对象。订单项与 order.OrderId 相关。我已验证 所有 ID 均已设置且正确,但是当我尝试保存(插入)订单时,我得到 INSERT 语句与 FOREIGN 冲突KEY 约束“FK_OrderItemDetail_Order”。冲突发生在数据库“MyData”、表“dbo.Order”、列“OrderId”中。
伪代码:
创建交易 交易开始() 插入订单 插入 order.LineItems实际代码:
... 实体.Validate(); 如果(实体.IsValid) { SetChangedProperties(实体); entity.Install.NagsInstallHours = entity.TotalNagsHours; foreach (OrderItemDetail orderItemDetail in entity.OrderItemDetailCollection) { 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); } 事务管理器.Commit(); } 抓住 { 如果(transactionManager.IsOpen) { transactionManager.Rollback(); } entity.EntityState = 原始实体状态; } } ...有人建议我需要使用两笔交易,一笔用于订单,另一笔用于订单项,但我有理由确定这是错误的。但是我已经为此奋斗了一天多,我需要解决它,这样我才能继续前进,即使这意味着使用不好的解决方法。我可能只是在做一些愚蠢的事情吗?
【问题讨论】:
-
看到上面的描述,您的订单ID似乎不是自动生成的。如果它是自动生成的,那么当您当时触发第一个 SQL 查询时,您将获得您需要在订单行中设置的订单 ID,以便第二个查询成功。
-
你能发布完整的代码吗?在第一个 ADO.NET 中,没有“环境事务”,您需要将每个操作的事务对象引用作为参数传递。如果您错过了这一点,那么您描述的行为很常见。
-
在一个事务中,任何事情都会发生或不发生,但操作仍然会一个接一个地发生。确保所有 SQL 命令都通过相同的事务。