Поделиться IDbConnection, чтобы сохранить транзакцию локальной
Репозиторий данных, который обрабатывает объект Data, наследуемый от универсального интерфейса, а уровень DAL реализован как универсальный класс, который получает универсальный интерфейс как внедрение зависимостей. Ниже приводится дизайн:
Data Entity - Автомобиль
public class Vehicle
{
public int Id {get; set;}
public string Brand {get; set;}
}
Общий интерфейс - IData
public interface IData<T>
{
IEnumerable<T> Select(IDictionary<string,object> parameters);
int Update(IDictionary<string,object> parameters);
int Delete(IDictionary<string,object> parameters);
int insert(IDictionary<string,object> parameters);
}
Автосервис
public class VehicleData : IData<Vehicle>
{
IEnumerable<Vehicle> Select(IDictionary<string,object> parameters)
{
using(IDbConnection conn = (Fetch Connection))
{
// Select Operation
}
}
int Update(IDictionary<string,object> parameters)
{
using(IDbConnection conn = (Fetch Connection))
{
// Update Operation
}
}
int Delete(IDictionary<string,object> parameters)
{
using(IDbConnection conn = (Fetch Connection))
{
// Delete Operation
}
}
int insert(IDictionary<string,object> parameters)
{
using(IDbConnection conn = (Fetch Connection))
{
// Insert Operation
}
}
}
Реализация класса DAL:
public class DAL<T>
{
public static IEnumerable<T> Select(IData<T> dataRepository, IDictionary<string,object> parameters)
{
return dataRepository.Select(parameters);
}
// Implementation for Insert, Update and Delete
}
Я выполняю VehicleData
с помощью DAL
из вызывающего класса следующим образом.
IData<Vehicle> vehicleData = new VehicleData();
IDictionary<string,object> parameters = // Filled from client
DAL<Vehicle>.Select(vehicleData,parameters);
Проблема, с которой я сталкиваюсь, заключается в том, что в каждом методе CRUD IDbConnection создается в Using
блок, таким образом расположенный в конце, как в локальном контексте, но есть сценарий, в котором несколько операций DAL над различными объектами должны быть частью единого контекста транзакции; если я продолжу аналогичным образом, открытый контекст транзакции будет повышен до распределенный уровень, так как открываются несколько ресурсов соединения, даже когда я могу сделать их в одном и том же контексте соединения, поскольку они выполняются один за другим. Проблема остается:
Как разделить соединение между несколькими звонками, как
DAL<Vehicle>.Update, DAL<Driver>.Update and DAL<Truck>.Update
, так что можно избежать продвижения транзакции с локального на распределенноеНе уверен, означает ли открытие и размещение соединения в контексте транзакции, что другое соединение может быть открыто без перехода в распределенную транзакцию, на мой взгляд, этого не произойдет
1 ответ
Используете ли вы контейнер IoC для внедрения зависимости? В IoC есть несколько стилей жизни (для потока, для веб-запроса и т. Д.). Например, с помощью Windsor Castle вы можете использовать стиль жизни Scoped. И ваш код будет выглядеть так:
Создать соединение (linq2db):
container.Register(
Component.For<DataConnection>().UsingFactoryMethod(x =>
CreateDataConnection()).LifestyleScoped(),
Component.For<IData<Vehicle>>()
.ImplementedBy<VehicleData>().LifestyleScoped()
);
private static DataConnection CreateDataConnection()
{
return new DataConnection(new SqlServerDataProvider("", SqlServerVersion.v2008),
@"Data Source=(local);Initial Catalog=DB1;Persist Security Info=True;User ID=user;Password=pwd");
}
Выполните некоторые операции с БД:
using (container.BeginScope())
{
var db = container.Resolve<DataConnection>();
db.BeginTransaction();
container.Resolve<IData<Vehicle>>().Update(...);
container.Resolve<IData<Vehicle>>().Update(...);
container.Resolve<IData<Vehicle>>().Update(...);
db.CommitTransaction();
}