问题描述
|
我在Visual Studio 2008中使用ASP.NET MVC2。我相信SQL Server是2005。我正在使用实体框架访问数据库。
下表具有基于
iRequest
和sCode
的复合主键:
RequestbyCount
iRequest integer
sCode varchar(10)
iCount integer
“ 0”是请求列表的外键。
更新请求后,我想为该请求清除现有的RequestbyCounts
,然后添加新的RequestbyCounts
。老行之间唯一的区别是计数。
对于我的代码,我尝试如下进行操作:
//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);
}
// 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
问题是,当我在不加注释的中间SaveChanges
行的情况下运行它时,它可以按需运行。但是我的理解是,这样做可以使交易分开。
如果我将中间的SaveChanges保留为上述注释,则该过程失败,并且我收到
违反PRIMARY KEY约束
\'PK_RequestbyCount \'。无法插入
对象中的重复键
\'dbo.RequestbyCount \'。\\ r \\ n语句
已终止。
显然,如果不执行中间的SaveChanges
,则不会按需删除旧行。
除非一切成功,否则我不希望保存结果。
我宁愿不采用以下方法:
//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**
}
}
我是否坚持执行上面的代码,该代码基本上对数据库进行了一些小调用以检查某项是否存在?
还是有某种方法告诉框架尝试删除我想要的行,但是如果插入新行失败,则回滚?
解决方法
您似乎根本没有使用事务。您需要包装所有代码
using (TransactionScope transaction = new TransactionScope())
{
...
transaction.Complete();
}
更好
using (TransactionScope transaction = new TransactionScope())
{
try
{
your code
transaction.Complete();
}
catch(Exception)
{
// handle error
}
}
使用try / catch块将确保如果发生异常(即您想要的异常),则不会提交事务。
有关Microsoft实体网站上的实体框架交易的更多信息。那里的解释很好。