sqlite поддерживает только 1 транзакцию? - PullRequest
3 голосов
/ 26 ноября 2009

При использовании ADO.NET (возможно, я ошибаюсь, я не знаю, как он называется), я замечаю, что могу начать транзакцию только с соединения, а команда, кажется, имеет команду. Транзакция, которая возвращает мне данные транзакции, но не начать транзакцию сам? На самом деле, глядя, я вижу это в System.Data.SQLite

// Summary:
    //     The transaction associated with this command. SQLite only supports one transaction
    //     per connection, so this property forwards to the command's underlying connection.
    [Browsable(false)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public SQLiteTransaction Transaction { get; set; }

То есть SQLite поддерживает только один период транзакции? я попытался открыть другое соединение, но затем моя транзакция вызвала исключение о блокировке БД. Таким образом, я не могу иметь более одного соединения одновременно?

Ответы [ 3 ]

4 голосов
/ 26 ноября 2009

Одна транзакция на соединение, да, но она может иметь более одного соединения (каждое со своей активной транзакцией).

Обновление: интересно. Я не знал о режиме общего кэша. Если ваше соединение использует этот режим, для всех соединений, использующих один и тот же общий кэш, доступна только одна транзакция. См. Режим совместного использования SQLite .

1 голос
/ 08 сентября 2011

В пределах 1 транзакции вы можете только читать / записывать в 1 соединение, пока транзакция не будет завершена. Следовательно, вы должны передать объект соединения, если вы выполняете бизнес-транзакцию, которая охватывает несколько SQL-операторов, например:

public class TimeTableService
    {
        ITimeTableDataProvider _provider = new TimeTableDataProvider();

        public void CreateLessonPlanner(WizardData wizardData)
        {
            using (var con = _provider.GetConnection())
            using (var trans = new TransactionScope())
            {
                con.Open();

                var weekListA = new List<Week>();
                var weekListB = new List<Week>();

                LessonPlannerCreator.CreateLessonPlanner(weekListA, weekListB, wizardData);

                _provider.DeleteLessonPlanner(wizardData.StartDate, con);

                _provider.CreateLessonPlanner(weekListA, con);
                _provider.CreateLessonPlanner(weekListB, con);

                _provider.DeleteTimeTable(TimeTable.WeekType.A, con);
                _provider.StoreTimeTable(wizardData.LessonsWeekA.ToList<TimeTable>(), TimeTable.WeekType.A, con);

                _provider.DeleteTimeTable(TimeTable.WeekType.B, con);
                _provider.StoreTimeTable(wizardData.LessonsWeekB.ToList<TimeTable>(), TimeTable.WeekType.B, con);

                trans.Complete();
            }
        }
    }

Ресурсы подключения и транзакции автоматически освобождаются / закрываются оператором using.

В каждом методе поставщика данных вы затем делаете

using(var cmd = new SQLiteCommand("MyStatement",con)
{
   // Create params + ExecuteNonQuery
}

Класс TransactionScope является новым в .NET 3.5 и автоматически выполняет откат в случае возникновения исключения. Простота в обращении ...

1 голос
/ 26 ноября 2009

Я не уверен насчет нескольких соединений, это, вероятно, связано с тем, что соединение блокирует файл, так как SQLite является файловой БД, а не серверной БД (на серверной БД сервер сохраняет все файлы заблокированными и обрабатывает одновременные соединения).

Вы можете одновременно открывать только одну транзакцию. Это должно иметь интуитивный смысл, поскольку все, что происходит после начала транзакции, относится к этой транзакции, либо до rollback, либо commit. Тогда вы можете начать новый. SQLite требует, чтобы все команды были в транзакции, поэтому, если вы не откроете новую вручную, она сделает это за вас.

Если вы беспокоитесь о вложенных транзакциях, вы можете подделать их с помощью savepoint. Документация

...