C# 如果';提交变更';失败,但需要其他提交?
在某些商业案例中,我的应用程序在事务内部存在错误原因。情况是这样的:C# 如果';提交变更';失败,但需要其他提交?,c#,.net,linq-to-sql,transactions,C#,.net,Linq To Sql,Transactions,在某些商业案例中,我的应用程序在事务内部存在错误原因。情况是这样的: static void MyFunc(DBContext context) { context.MyObjects.InsertOnSubmit(new MyObj{Id=1}); // Id - is a primary key context.MyObjects.InsertOnSubmit(new MyObj{Id=1});
static void MyFunc(DBContext context)
{
context.MyObjects.InsertOnSubmit(new MyObj{Id=1});
// Id - is a primary key
context.MyObjects.InsertOnSubmit(new MyObj{Id=1});
// here I force system to fail
// by trying to add record with
// duplicated primary key value
context.SubmitChanges(); // causes an error (as expected)
}
static void main()
{
using (DBContext context = new DBContext())
{
try
{
using (TransactionScope scope = CreateTransactionScope())
{
MyFunc(context);
scope.Complete();
}
}
catch(Exception exc)
{
MyLog log = new MyLog{...valid object data... want to log error ... };
context.MyLogs.InsertOnSubmit(log);
context.SubmitChanges();
}
}
}
这里的问题是,尝试保存“日志”对象会导致尝试将以前添加的对象保存到“MyObject”表中!因此,我无法保存日志记录。。。我的“main”函数抛出一个异常
我怎样才能解决这个问题?欢迎有任何想法
(我正在使用MS SQL 2005、Linq2Sql、.NET 3.5和.NET 4.0的想法也很受欢迎!)
另外,我知道调用“scope.Rollback”可能是个好主意,但是如果我离开“using(TransactionScope scope…”,而不调用“Complete”,那么“Rollback应该自动应用…”
p.p.S.我可以创建一个新的“DBContext”对象,但我认为这是不合理的。一般来说,DataContext将在内存中保留对从它加载或附加到它的所有对象的引用。我可能错了,但我不相信TransactionScope中的更改会回滚到“内存中”对象中
因此,错误处理程序中上下文上的SubmitChanges()将尝试重新提交对“内存中”模型的所有更改。我所知道的纠正这种情况的唯一方法是通过创建新上下文来重置“内存中”模型 事务是一种工具,用于对必须作为整体而不是部分执行的操作进行分组。由于您有一些操作可以(并且在您的情况下必须)轻松地与其他操作分离,因此使用两个单独的事务似乎更合适。您可以在这样的上下文中回滚
public void Rollback()
{
base.ChangeTracker.Entries().ToList().ForEach(entry => entry.State = System.Data.EntityState.Unchanged);
}
为什么创建单独的上下文不是一个合理的解决方案?如果有任何其他方法-我宁愿。。。否则-是的,这将是一个解决方案。。。问题是:我预计在将来的其他情况下,我的业务逻辑可能会在提交更改期间导致错误,但仍需要在同一调用(在同一上下文中)中进行其他更改。。。而使用上下文对我来说并不是很有吸引力。如果你想在其他数据失败的情况下写入一些数据,你有两个简单的选择:1)使用单独的上下文,2)使用单独的事务。但这不会将内存中的对象校正为当前的数据库对象,对吗?如果以后,在DbContext和该对象的生存期内,您修改了该对象上的另一个属性,那么由于其他属性仍然是脏的,它们也可以保存回数据库(取决于检测更改设置)。这不是回滚,它只是防止更改被持久化