gpt4 book ai didi

c# - SQL 服务器 : is there any performance penalty for wrapping a SELECT query in a transaction?

转载 作者:太空宇宙 更新时间:2023-11-03 18:58:23 27 4
gpt4 key购买 nike

作为学习练习,在尝试使用任何 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/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com