如何回滚与LINQ to SQL相关的事务?

问题只是回滚变化,而不是提交。

假设我获取了一些数据,我更改了它们,我提交了更改(可选步骤)并且我回滚了事务。 无论你在哪里看每个作者写,这都会取消更改。

但我发现这是半真的 – LINQ DataContext将保留更改的数据! 我使用TransactionScope和DataContext.Transaction测试了这个。 在这两种情况下,我都有相同的行为。

解决方法是在回滚后重新创建DataContext(但这会导致其他问题,如缓存数据和处理嵌套事务)或手动丢弃DataContext中的更改。 然而,这些只是解决方法。

问题

那么我错过了什么? LINQ to SQL不适合交易吗? 如何使用交易,以便他们真的回滚变化?

MyTable record = null; db.Connection.Open(); using (db.Transaction = db.Connection.BeginTransaction()) { record = db.MyTable.First(); record.BoolField = !record.BoolField; // changed db.SubmitChanges(); db.Transaction.Rollback(); } 

数据上下文应被视为工作单元。 您制作的细节取决于您 – 它可以是页面请求,也可以是单个操作; 但是 – 如果你得到一个例外(或几乎任何意外) – 停止 ; 放弃数据上下文和回滚。 回滚后,您的数据上下文将会混淆,所以不要保留它

另外; 不要将数据上下文保留的时间超过必要的时间。 它不是一个app-long数据缓存。

您似乎要求的是数据库(或其某些部分)的内存缓存,而不是轻量级ORM。 我会说LINQ to SQL对于事务和轻量级ORM来说都很好,但是开箱即用作为数据库缓存并不是那么好。 在我看来,数据上下文最适合使用工作单元模式。 为特定任务创建上下文,执行任务,然后处理上下文。 如果任务恰好包含失败的事务,那么您需要弄清楚如何响应失败。 这可以通过更正错误并使用现有上下文重试,或者在Web上下文中将尝试的更改传递回用户,然后在重新提交数据时再次尝试使用新上下文。

两件事情:

1)陈旧的datacontext

你观察到的通常被称为“陈旧的”datacontext。 datacontext中的实体不会注意到您的rollbak。 如果在submitchanges之后执行存储过程,则会得到类似的行为。 datacontext也不会注意到这一点。 但是,您的交易将在数据库中回滚! (同样,存储过程将被执行)

2)关于交易

无需管理交易。 Linq2Sql已经在Submitchanges中为您创建了一个事务。 如果你真的想要管理事务(例如,通过多个datacontexts或存储过程与一些linq2sql结合使用,请将整个内容包装在TransactionScope中。在您要提交的位置调用transaction.Complete()。