First, a little background (greatly simplified): I have two classes, one called Entity and one called Item which a subclass of Entity. They each store their individual properties in seperate SQL 2008 tables using TableAdapters generated by a strongly typed DataSet. The Entity class has a Save() method that looks like this:
Public Sub Save()
entityTableAdapter.Update(entityRow)
End Sub
and the Item class has a Save method which looks like this:
Public Overrides Sub Save()
MyBase.Save
itemTableAdapter.Update(itemRow)
End Sub
This works well except that if inserting an Item row fails then I am left with an orphaned Entity row in the database so I extended the TableAdapters and Save methods to use a transaction like so:
Entity Save method:
Public Sub Save(tx as SqlTransaction)
entityTableAdapter.Connection = tx.Connection
entityTableAdapter.Transaction = tx
entityTableAdapter.Update(entityRow)
End Sub
Item Save method:
Public Overrides Sub Save()
// setup the transaction:
dim cn as SqlConnection = itemTableAdapter.Connection
cn.Open
dim tx as Sql Transaction = cn.BeginTransaction
// save the base object properties:
MyBase.Save(tx)
// save this object's properties:
itemTableAdapter.Connection = cn
itemTableAdapter.Transaction = tx
itemTableAdapter.Update(itemRow)
// commit the transaction
tx.Commit
End Sub
Now when I attempt to save a new Item everything works up to the itemTableAdapter.Update(itemRow) where I get an error similar to
INSERT statement conflicted with the
FOREIGN KEY constraint… column
‘EntityID’
Indeed, the SQL table does not contain a row in the Entity table with the necessary ID at this point because the transaction is not complete.
Am I going about this the wrong way? My goal is to prevent the Entity record from being inserted if inserting the Item record fails. I could write code to delete the Entity record again, but this does not seem very elegant to me…
The code above has been greatly simplified to illustrate the problem. I am happy to post more details if it helps.
Thanks in advance for any help!
JE
The way to handle situations like this in some databases (e.g. Oracle, PostgreSQL) would be to use deferrable contraints. Unfortunately it appears that SQL Server does not as yet support deferrable constraints. About the only thing I can think of is to add logic to your app to delete the unnecessary Entity if the Item insert fails for some other reason.
Share and enjoy.