tags:

views:

396

answers:

6

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?

A: 

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.

IronGoofy
I have set the primary key in the order before I Insert it. It is the same value after the insert statement. All the line items have also had the related orderid set before trying to insert them.
Beaner
What is the FK constraint checking for? Please add some more information, it may point to another area than the PK of table order ...
IronGoofy
The FK is the OrderItem.OrderId column to the PK Order.OrderId. If I save and commit the Order, then try saving the OrderItems, it works fine.
Beaner
Hmmm .. this makes it sound like you are in fact using two different transactions for your inserts.
IronGoofy
A: 

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.

Roberto Aloi
A: 

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.

Joel Coehoorn
Please understand that I didn't show error handling, rolling back the transaction, etc. For the sake of brevity I tried to show only the summary of the problem without the detail. If it turns out the detail is needed I will post actual code
Beaner
A: 

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 ?

Charles Bretana
Yes. I am using GUIDs for Ids and the primary key and foreign keys are all set before the transaction is opened and all have been checked just before and immediately after the insert statements.
Beaner
Then the next thing I'd check is to make sure that the Foreign Key Constraint being referenced in the error message is in fact connecting the correct two tables.. and that it is going in the correct direction. ... and between the right two columns
Charles Bretana
+1  A: 

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.

Jason
1. Yes, there is no where for the connection to be closed from inside the transaction.2. I am setting the ID myself, explicitly before saving the records, and I have checked after the Order is inserted to confirm the ID was not changed by SQL.3. Not ruling out having done something wrong, but the constraint is nothing more than a FK OrderItem.OrderId to PK Order.OrderId.
Beaner
+1  A: 

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.

Chris
Deleted the FK, saved the table, added the FK back and regenerated the scripts. Success. I had regenerated a dozen times before this hoping it would fix the problem and nothing, so I don't think it was nettiers, but it's working now so I'm a happy camper.
Beaner