SQL 事务如何工作?

发布于 2024-08-09 15:17:16 字数 1854 浏览 6 评论 0原文

我从事 SQL 工作的时间并不长,但我想我明白,通过将 SQL 语句包装在事务中,所有语句都完成,或者没有一个语句完成。这是我的问题。我有一个包含 lineitem 集合的订单对象。行项目在 order.OrderId 上相关。我已验证所有 ID 均已设置且正确,但当我尝试保存(插入)订单时,我收到INSERT 语句与 FOREIGN 冲突键约束“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;
    }
}
...

有人建议我需要使用两个事务,一个用于订单,一个用于行项,但我有理由确信这是错误的。但我已经为此奋斗了一天多了,我需要解决它,这样我就可以继续前进,即使这意味着使用一个糟糕的解决方法。我可能只是做了一些愚蠢的事情吗?

I have not been working in SQL too long, but I thought I understood that by wrapping SQL statements inside a transaction, all the statements completed, or none of them did. Here is my problem. I have an order object that has a lineitem collection. The line items are related on order.OrderId. I have verified that all the Ids are set and are correct but when I try to save (insert) the order I am getting The INSERT statement conflicted with the FOREIGN KEY constraint "FK_OrderItemDetail_Order". The conflict occurred in database "MyData", table "dbo.Order", column 'OrderId'.

psuedo code:

create a transaction
transaction.Begin()
Insert order
Insert order.LineItems <-- error occurs here
transaction.Commit

actual code:

...
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;
    }
}
...

Someone suggested I need to use two transactions, one for the order, and one for the line items, but I am reasonably sure that is wrong. But I've been fighting this for over a day now and I need to resolve it so I can move on even if that means using a bad work around. Am I maybe just doing something stupid?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

痴骨ら 2024-08-16 15:17:16

我注意到您说您正在使用 NetTiers 进行代码生成。

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

祝你的问题好运。

I noticed that you said you were using NetTiers for your code generation.

I've used NetTiers myself and have found that if you delete your foreign key constraint from your table, add it back to the same table and then run the build scripts for NetTiers again after making your changes in the database might help reset the data access layer. I've tried this on occasion with positive results.

Good luck with your issue.

梦毁影碎の 2024-08-16 15:17:16

如果没有看到你的代码,很难说问题是什么。它可以是任意数量的东西,但看看这些:

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

您绝对不想使用两个事务。

Without seeing your code, it is hard to say what the problem is. It could be any number of things, but look at these:

  1. This is obvious, but your two insert commands are on the same connection (and the connection stays open the whole time) that owns the transaction right?
  2. Are you retrieving your ID related to the constraint after the first insert and writing it back into the data for second insert before executing the command?
  3. The constraint could be set up wrong in the DB.

You definitely do not want to use two transactions.

花期渐远 2024-08-16 15:17:16

看来您的 lineItems 插入语句未正确设置订单的值。这应该是 Insert order 步骤的结果。您是否查看(并测试)了各个 SQL 语句?

我不认为你的问题与事务控制有任何关系。

Looks like your insert statement for the lineItems is not correctly setting the value for the order .. this should be a result of the Insert order step. Have you looked (and tested) the individual SQL statements?

I do not think your problem has anything to do with transaction control.

忘你却要生生世世 2024-08-16 15:17:16

我对此没有经验,但看起来您可能指定了父表中不可用的键值。抱歉,但我无法为您提供更多帮助。

I have no experience with this, but it looks like you might have specified a key value that is not available in the parent table. Sorry, but I cannot help you more than this.

生死何惧 2024-08-16 15:17:16

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

The problem is how you handle the error. When an error occurs, a transaction is not automatically rolled back. You can certainly (and probably should) choose to do that, but depending on your app or where you are you may still want to commit it. And in this case, that's exactly what you're doing. You need to wrap some error handling code around there to rollback your code when the error occurs.

演多会厌 2024-08-16 15:17:16

该错误看起来像是未向 LineItem 提供正确的 FK OrderId,该 ID 是通过将订单插入订单表而自动生成的。你说你已经检查了Ids,你是否也检查了订单详细信息中的FK?

The error looks like that the LineItems are not being given the proper FK OrderId that was autogenerated by the the insert of the Order to the Order Table. You say you have checked the Ids, Have you checked the FKs in the order details as well ?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文