Я только что начал использовать Dapper для проекта, в основном использующий ORM, такие как NHibernate и EF в течение последних нескольких лет.
Обычно в наших веб-приложениях мы реализуем сеанс на запрос, начинаем транзакцию в начале запроса и фиксируем его в конце.
Должны ли мы делать что-то подобное при прямой работе с SqlConnection/System.Transactions?
Как это делает StackOverflow?
Решение
Принимая советы как @gbn, так и @Sam Safron, я не использую транзакции. В моем случае я делаю только запросы на чтение, поэтому, похоже, нет реального требования использовать транзакции (вопреки тому, что мне рассказали о неявных транзакциях).
Я создаю легкий интерфейс сеанса, чтобы я мог использовать соединение для каждого запроса. Это очень полезно для меня, так как с Dapper мне часто нужно создавать несколько разных запросов для создания объекта и, скорее, использовать одно и то же соединение.
Работа по определению местоположения для каждого запроса и его утилизации выполняется моим контейнером IoC (StructureMap):
public interface ISession : IDisposable {
IDbConnection Connection { get; }
}
public class DbSession : ISession {
private static readonly object @lock = new object();
private readonly ILogger logger;
private readonly string connectionString;
private IDbConnection cn;
public DbSession(string connectionString, ILogger logger) {
this.connectionString = connectionString;
this.logger = logger;
}
public IDbConnection Connection { get { return GetConnection(); } }
private IDbConnection GetConnection() {
if (cn == null) {
lock (@lock) {
if (cn == null) {
logger.Debug("Creating Connection");
cn = new SqlConnection(connectionString);
cn.Open();
logger.Debug("Opened Connection");
}
}
}
return cn;
}
public void Dispose() {
if (cn != null) {
logger.Debug("Disposing connection (current state '{0}')", cn.State);
cn.Dispose();
}
}
}