我正在使用transactionscope来确保正确地将数据读入数据库。但是,我可能需要在事务运行时选择一些数据(来自另一个页面)。可以这样做吗?在数据库方面,我非常棒。
我正在使用LinqToSQL和SQL Server 2005(dev)/ 2008(prod)。
答案 0 :(得分:1)
是的,在事务运行时仍可以从数据库中选择数据。
通常可以从其他事务中读取不受事务影响的数据(例如,表中未更新的行)。 (在某些情况下,SQL Server将引入一个表锁,它会停止对表中所有行的读取,但它们不常见,并且通常是查询或服务器上发生其他事情的症状)。
您需要查看Transaction Isolation Levels,因为它们可以准确控制此行为的工作方式。
以下是设置事务范围隔离级别的C#代码。
TransactionOptions option = new TransactionOptions();
options.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;
using (TransactionScope sc = new TransactionScope(TransactionScopeOption.Required, options)
{
// Code within transaction
}
通常,根据事务中指定的事务隔离级别(或任何表提示,如NOLOCK),您将获得不同级别的数据锁定,以保护应用程序的其余部分免受事务中的活动影响。例如,事务隔离级别为READUNCOMMITTED
,您可以在事务发生时查看该事务中的写入。这允许脏读,但也防止(大多数)数据锁。
比例的另一端是SERIALIZABLE
之类的隔离级别,可确保您的交易活动完全隔离,直到它已经完成。
答案 1 :(得分:0)
是的,默认情况下,TransactionScope
将锁定事务中涉及的表。如果您需要在进行交易时阅读,请使用TransactionScope
TransactionOptions
输入另一个IsolationLevel.ReadUncommitted
:
TransactionScopeOptions = new TransactionScopeOptions();
options.IsolationLevel = IsolationLevel.ReadUncommitted;
using(var scope = new TransactionScope(
TransactionScopeOption.RequiresNew,
options
) {
// read the database
}
使用LINQ-to-SQL DataContext
:
// db is DataContext
db.Transaction =
db.Connection.BeginTransaction(System.Data.IsolationLevel.ReadUncommitted);
请注意System.Transactions.IsolationLevel
和System.Data.IsolationLevel
之间存在差异。是的,你读得正确。
答案 2 :(得分:0)
对于已提供的建议,我强烈建议您研究快照隔离模型。在Using Snapshot Isolation进行了很好的讨论。在数据库上启用Read Committed Snapshot ON可以缓解许多争用问题,因为读者不再被编写者阻止。由于默认读取是在读取提交隔离模式下执行的,因此这个简单的数据库选项开关具有直接的好处,并且不需要更改应用程序。
没有免费的午餐,所以这是有代价的,在这种情况下,价格是对tempdb的附加负载,请参阅Row Versioning Resource Usage。
如果您使用的是explict隔离级别,特别是如果您使用默认的TransactionScope Serializable模式,那么您必须检查您的代码以强制执行更多的ReadCommited隔离级别。如果您不知道您使用的隔离级别,则表示您使用ReadCommited。