作为学习练习,在尝试使用任何 ORM(如 EF)之前,我想使用 ADO.NET 和存储过程构建一个个人项目。
因为我不希望我的代码随着时间的推移变得一团糟,所以我想使用一些模式,例如存储库和 UoW 模式。
除了事务处理之外,我几乎什么都弄明白了。
为了以某种方式“模拟”UoW,我使用了 this class由@jgauffin 提供,但阻止我使用该类的是,每次您创建该类的新实例 (AdoNetUnitOfWork
) 时,您都会自动开始一个事务,并且在很多情况下您只需要读取数据。
在这方面,这是我在我一直在阅读的一本 SQL 书籍中找到的内容:
Executing a SELECT statement within a transaction can create locks on the referenced tables, which can in turn block other users or sessions from performing work or reading data
这是 AdoNetUnitOfWork
类:
public class AdoNetUnitOfWork : IUnitOfWork
{
public AdoNetUnitOfWork(IDbConnection connection, bool ownsConnection)
{
_connection = connection;
_ownsConnection=ownsConnection;
_transaction = connection.BeginTransaction();
}
public IDbCommand CreateCommand()
{
var command = _connection.CreateCommand();
command.Transaction = _transaction;
return command;
}
public void SaveChanges()
{
if (_transaction == null)
throw new InvalidOperationException("Transaction have already been commited. Check your transaction handling.");
_transaction.Commit();
_transaction = null;
}
public void Dispose()
{
if (_transaction != null)
{
_transaction.Rollback();
_transaction = null;
}
if (_connection != null && _ownsConnection)
{
_connection.Close();
_connection = null;
}
}
}
这就是我想在我的存储库中使用 UoW 的方式:
public DomainTable Get(int id)
{
DomainTable table;
using (var commandTable = _unitOfWork.CreateCommand())
{
commandTable.CommandType = CommandType.StoredProcedure;
//This stored procedure contains just a simple SELECT statement
commandTable.CommandText = "up_DomainTable_GetById";
commandTable.Parameters.Add(commandTable.CreateParameter("@pId", id));
table = ToList(commandTable).FirstOrDefault();
}
return table;
}
我知道我可以稍微调整一下这段代码,以便事务是可选的,但是由于我试图使这段代码尽可能独立于平台,而且据我所知,在其他持久性框架(如 EF)中你没有手动管理事务,问题是,如果按原样使用此类,即始终创建事务,我是否会造成某种瓶颈?
最佳答案
这一切都取决于 transaction isolation level .如果使用默认隔离级别(即读取已提交),那么如果包含在事务中,您的 SELECT
应该不会出现性能损失。如果语句尚未启动,SQL Server 无论如何都会在内部将语句包装在事务中,因此您的代码的行为应该几乎相同。
但是,我必须问你为什么不使用内置的 .Net TransactionScope
?这样您的代码将与其他库和框架更好地交互,因为 TransactionScope
被普遍使用。如果您决定切换到这个,我必须警告您,默认情况下,TransactionScope
使用 SERIALIZABLE 隔离级别,这会导致性能下降,请参阅 using new TransactionScope() Considered Harmful .
关于c# - SQL 服务器 : is there any performance penalty for wrapping a SELECT query in a transaction?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40197865/