У меня есть следующий код, который находится в транзакции. Я не уверен, где/когда я должен фиксировать свою единицу работы.
Нарочно, я не упомянул, какой Respoistory я использую - например, Linq-To-Sql, Платформа Объекта 4, NHibernate, и т.д.
Если кто-то знает, где, они могут объяснить, ПОЧЕМУ они сказали, где? (я пытаюсь понять шаблон через пример (примеры), в противоположность просто тому, чтобы заставлять мой код работать).
Вот то, что у меня есть:-
using
(
TransactionScope transactionScope =
new TransactionScope
(
TransactionScopeOption.RequiresNew,
new TransactionOptions
{ IsolationLevel = IsolationLevel.ReadUncommitted }
)
)
{
_logEntryRepository.InsertOrUpdate(logEntry);
//_unitOfWork.Commit(); // Here, commit #1 ?
// Now, if this log entry was a NewConnection or an LostConnection,
// then we need to make sure we update the ConnectedClients.
if (logEntry.EventType == EventType.NewConnection)
{
_connectedClientRepository.Insert(
new ConnectedClient { LogEntryId = logEntry.LogEntryId });
//_unitOfWork.Commit(); // Here, commit #2 ?
}
// A (PB) BanKick does _NOT_ register a lost connection,
// so we need to make sure we handle those scenario's as a LostConnection.
if (logEntry.EventType == EventType.LostConnection ||
logEntry.EventType == EventType.BanKick)
{
_connectedClientRepository.Delete(
logEntry.ClientName, logEntry.ClientIpAndPort);
//_unitOfWork.Commit(); // Here, commit #3 ?
}
_unitOfWork.Commit(); // Here, commit #4 ?
transactionScope.Complete();
}
Фиксация на # 4 после выполнения всех операций со всеми репозиториями. Если вы зафиксируете заранее, изменения, сделанные после этого вызова, не будут зафиксированы.
Предполагая, что ваше хранилище данных присваивает идентификаторы, вы должны зафиксировать #1 (с NHibernate вы должны даже промыть), затем в конце #4.
Хорошей отправной точкой для ответа на этот вопрос является определение единицы работы из шаблонов архитектуры предприятия ( http://martinfowler.com/eaaCatalog/unitOfWork.html ):
Поддерживает список объектов, затронутых бизнес-транзакцией, и координирует запись изменений и решение проблем параллелизма.
Границы вашей единицы работы определяются границами вашей бизнес-транзакции - в данном случае это синоним границ транзакции базы данных (но в случае длительной бизнес-транзакции, которая охватывает несколько запросов, которые могут не так).
Работая в обратном направлении от приведенного выше определения и основываясь на моем понимании показанного фрагмента кода, вы должны зафиксировать единицу работы в конце бизнес-транзакции (№4).
Кроме того, области транзакций вашей базы данных всегда должны быть меньше, чем область действия вашего UoW (т.е. область tx находится между вызовом UoW.Begin () и UoW.Commit ()). Если ваш UoW охватывает несколько транзакций базы данных, вы должны использовать компенсирующую транзакцию, чтобы «перебалансировать» UoW, если одна из внутренних транзакций не удалась. В этом случае, особенно если ваш UoW создает собственные границы транзакции базы данных в UoW.Begin () и UoW.Commit (), я бы удалил область транзакции, поскольку это просто добавляет ненужный шум в код.