Запись транзакций в С# и Windows?

У меня есть файл данных, и время от времени мне нужно записать изменения в файл. Изменение состоит из изменения информации в нескольких местах. Например, изменение некоторых данных ближе к концу файла, а также изменение некоторой информации рядом с началом. Я хочу, чтобы две отдельные записи были либо успешными, либо обе неудачными, иначе они останутся в неопределенном состоянии и будут эффективно повреждены. Есть ли встроенная поддержка этого сценария в .NET или вообще?

Если нет, то как другим решить эту проблему? Как база данных Windows решает эту проблему?

UPDATE. Я не хочу использовать возможности Transactional NTFS, потому что он недоступен в старой версии Windows, такой как XP, и медленнее в сценарии перезаписывания файлов, как описано выше.

Ответ 1

Если вы используете Windows 6 или более позднюю версию (Vista/7/2008/2008R2), файловая система NTFS поддерживает транзакции (в том числе в рамках распределенной транзакции): но вам нужно будет использовать P/Invoke для вызова Win32 API (см. этот question).

Если вам нужно запустить более старые версии Windows или разделы, отличные от NTFS, вам нужно будет выполнить транзакции самостоятельно. Это явно нетривиально: получение полной функциональности ACID при обработке нескольких процессов (включая удаленный доступ через общие ресурсы) при сбоях процессов и систем даже при условии, что будут использоваться только ваши методы доступа (какой-то другой процесс с использованием обычных API Win32, конечно, будет сломать вещи).

В этом случае база данных почти наверняка будет проще: есть несколько встроенных баз данных (SQL Compact Edition, SQL Lite,...), поэтому для базы данных не требуется серверный процесс.

Ответ 2

DB в основном использует концепцию журнала (по крайней мере, те, о которых я знаю). Идея заключается в том, что операция записи записывается в журнал до тех пор, пока Writer не совершит транзакцию. (Конечно, это просто базовое описание, это так просто)

В вашем случае это может быть копия вашего файла, где вы собираетесь писать данные, и если все закончится с успехом, замените исходный файл на него копией.

Подстановка: переименуйте исходный файл, например, old, переименуйте файл резервной копии, такой как original.

Если сбой подстановки: это критическая ошибка, которую приложение должно обрабатывать с помощью стратегий отказоустойчивости. Может быть, он сообщил пользователю о неудачной операции сохранения и пытается восстановить. Кстати, в любой момент у вас есть обе копии вашего файла. Это когда операция записи только началась, а другая - при завершении операции записи.

Эти методы мы использовали в прошлых проектах на VS IDE, таких как системы промышленного контроля, с довольно хорошим успехом.