在某些商业案例中,我的应用程序在交易内部出错。情况如下:
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();
}
}
}
这里的问题是尝试保存'log'对象会导致尝试将以前添加的对象保存到'MyObject'表中!结果我无法保存日志记录...而我的'main'函数抛出异常......
我怎么解决这个问题?欢迎任何想法。
(我正在使用MS SQL 2005,Linq2Sql,.NET 3.5,欢迎使用.NET 4.0的想法!)
P.S。我知道调用'scope.Rollback'可能是一个好主意,但是如果我在不调用'Complete'的情况下离开'using(TransactionScope scope ...)'那么'应该自动应用Rollback ......
P.P.S。我可以创建一个新的'DBContext'对象,但不认为它是合理的。
答案 0 :(得分:4)
事务是一种工具,用于对必须作为整体执行的操作进行分组,而不是部分执行。既然你有一些行动可以(并且在你的情况下必须)很容易与其他行动分开,那么使用两个单独的交易似乎更合适。
答案 1 :(得分:1)
一般来说,DataContext将保留对内存中加载或附加到其中的所有对象的引用。我可能是错的,但我不相信TransactionScope中的更改会在“内存中”对象中回滚。
因此,错误处理程序中的上下文中的SubmitChanges()将尝试重新提交对“内存中”模型的所有更改。我所知道的唯一解决方法是通过创建新的上下文来重置“内存中”模型。
答案 2 :(得分:1)
你可以在这样的上下文中回滚
public void Rollback()
{
base.ChangeTracker.Entries().ToList().ForEach(entry => entry.State = System.Data.EntityState.Unchanged);
}