Entity framework transaction error after deleting a row and inserting a new row with same primary key
I am using ASP.NET MVC2 in Visual Studio 2008. I believe the SQL Server is 2005. I am using Entity Framework to access the database.
I've got the following table with a composite primary key based upon iRequest
and sCode
:
RequestbyCount
iRequest integer
sCode varchar(10)
iCount integer
iRequest
is a foreign key to a list of requests.
When a request is updated, I want to clear out the existing RequestbyCounts
for that request and then add in the new RequestbyCounts
. More than likely, the only difference between the old rows will be the Count.
For my code, I attempt it as follows:
//delete ALL our old requests
var oldEquipList = (from eq in myDB.dbEquipmentRequestedbyCountSet
where eq.iRequestID == oldData.iRequestID
select eq).ToList();
foreach (var oldEquip in oldEquipList)
{
myDB.DeleteObject(oldEquip);开发者_Go百科
}
// myDB.SaveChanges(); <---- adding this line makes it work
//add in our new requests
foreach (var equip in newData.RequestList) //newData.RequestList is a List object
{
if (equip.iCount > 0)
{
//add in our actual request items
RequestbyCount reqEquip = new RequestbyCount();
reqEquip.sCodePrefix = equip.sCodePrefix;
reqEquip.UserRequest = newRequest;
reqEquip.iCount = equip.iCount;
myDB.AddToRequestbyCount(reqEquip);
}
}
myDB.SaveChanges(); //save our results
The issue is when I run it with the intermediate SaveChanges
line uncommented, it works as desired. But my understanding is that doing this breaks the transaction apart.
If I leave the intermediate SaveChanges commented out as above, the process fails and I receive a
Violation of PRIMARY KEY constraint 'PK_RequestbyCount'. Cannot insert duplicate key in object 'dbo.RequestbyCount'.\r\nThe statement has been terminated.
Obviously, without doing the intermediate SaveChanges
, the old rows are NOT removed as desired.
I do NOT want the results saved unless everything succeeds.
I would rather not take the following approach:
//add in our new requests
foreach (var equip in newData.RequestList)
{
if (equip.iCount > 0) && (**it isn't in the database**)
{
//add in our actual request items
RequestbyCount reqEquip = new RequestbyCount();
reqEquip.sCodePrefix = equip.sCodePrefix;
reqEquip.UserRequest = newRequest;
reqEquip.iCount = equip.iCount;
myDB.AddToRequestbyCount(reqEquip);
} else if (**it is in the database**) && (equip.iCount == 0) {
**remove from database**
} else {
**edit the value in the database**
}
}
Am I stuck doing the above code that basically makes a bunch of little calls to the database to check if an item exists?
Or is there some method that tell the framework to attempt to delete the rows I want but rollback if there is a failure inserting the new rows?
You don't appear to be using transactions at all. You need to wrap all your code in
using (TransactionScope transaction = new TransactionScope())
{
...
transaction.Complete();
}
Even better
using (TransactionScope transaction = new TransactionScope())
{
try
{
your code
transaction.Complete();
}
catch(Exception)
{
// handle error
}
}
Using the try/catch block will ensure that the transaction is not committed if an exception occurs, which is what you stated you wanted.
Lot's more on entity framework transactions at Microsoft's web site. The explanations there are quite good.
精彩评论