У меня есть родительский объект (часть DAL), который содержит, помимо прочего, коллекцию (List<t>
) дочерних объектов.
Когда я сохраняю объект обратно в БД, я ввожу / обновляю родительский элемент, а затем перебираю каждый дочерний элемент. Для удобства обслуживания я поместил весь код для ребенка в отдельный закрытый метод.
Я собирался использовать стандартные транзакции ADO, но в своих путешествиях я наткнулся на объект TransactionScope, который, как мне кажется, позволит мне обернуть все взаимодействия с БД в родительском методе (вместе со всем взаимодействием в дочернем методе) в одна транзакция.
Пока все хорошо ..?
Итак, следующий вопрос - как создавать и использовать соединения в этом TransactionScope. Я слышал, что использование нескольких соединений, даже если они подключены к одной и той же БД, может заставить TransactionScope думать, что это распределенная транзакция (включающая дорогостоящую работу DTC).
Это тот случай? Или это, как я, кажется, читаю в другом месте, случай, когда использование той же строки соединения (которая поддается пулу соединений) будет в порядке?
С практической точки зрения, я ...
- Создание отдельных соединений в родительском и дочернем элементах (хотя и с одной и той же строкой соединения)
- Создать соединение в родительском объекте и передать его в качестве параметра (мне кажется неуклюжим)
- Делай что-нибудь еще ...?
UPDATE:
Хотя кажется, что я буду в порядке, используя мои обычные .NET3.5 + и SQL Server 2008+, другая часть этого проекта будет использовать Oracle (10g), поэтому я мог бы также практиковать технику, которая может быть используется последовательно в разных проектах.
Поэтому я просто передам соединение дочерним методам.
Вариант 1 Пример кода:
using (TransactionScope ts = new TransactionScope())
{
using (SqlConnection conn = new SqlConnection(connString))
{
using (SqlCommand cmd = new SqlCommand())
{
cmd.Connection = conn;
cmd.Connection.Open();
cmd.CommandType = CommandType.StoredProcedure;
try
{
//create & add parameters to command
//save parent object to DB
cmd.ExecuteNonQuery();
if ((int)cmd.Parameters["@Result"].Value != 0)
{
//not ok
//rollback transaction
ts.Dispose();
return false;
}
else //enquiry saved OK
{
if (update)
{
enquiryID = (int)cmd.Parameters["@EnquiryID"].Value;
}
//Save Vehicles (child objects)
if (SaveVehiclesToEPE())
{
ts.Complete();
return true;
}
else
{
ts.Dispose();
return false;
}
}
}
catch (Exception ex)
{
//log error
ts.Dispose();
throw;
}
}
}
}