How to rollback data changes in DBContext if 'SubmitChanges' failed but other submits are required?
In some business cases my app I have error cause inside of transaction. Situation looks like this:
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();
        }
    }
}
the problem here is that attempt to save 'log' object causes attempt to save previously added objects into 'MyObject' table too! And as a result I can't save log record... and my 'main' function throws an exception...
How could I resolve that? Any thoughts are welcome.
(I'm using MS SQL 2005, Linq2Sql, .NET 3.5, ideas for .NET 4.0 are also welcome!)
P.S. I know it could be a good idea to call 'scope.Rollback', but if I leave 'using (TransactionScope scope ...)' without calling 'Complete' then 'Rollback should be applied automatically...
P.P.S. I could create a new 'DBContext' object, but don开发者_StackOverflow社区't think it is reasonable.
A transaction is a tool to group actions that must be performed as a whole, not in parts. Since you have some actions that can (and in your case must) be easily separated from the rest, it seems a lot more appropriate to use two separate transactions.
Generally speaking, the DataContext will keep a reference to all the objects that were loaded from or attached to it in memory. I could be wrong, but I do not believe the changes within the TransactionScope are rolled back in the "in-memory" objects.
Therefore SubmitChanges() on the context in the error handler will try to resubmit all the changes to the "in-memory" model. The only way I know of to correct this is to reset the "in-memory" model by creating a new context.
you can rollback in context like this
public void Rollback()
{
    base.ChangeTracker.Entries().ToList().ForEach(entry => entry.State = System.Data.EntityState.Unchanged);
}
 
         加载中,请稍侯......
 加载中,请稍侯......
      
精彩评论