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?
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.
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 ?
Without seeing your code, it is hard to say what the problem is. It could be any number of things, but look at these:
You definitely do not want to use two transactions.
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.
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.
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.