Надежная вставка с SQLite - PullRequest
       22

Надежная вставка с SQLite

1 голос
/ 06 декабря 2009

Я пишу программу на C #, которая должна вставлять данные в несколько таблиц. Первая вставка возвращает последний идентификатор строки вставки, который, в свою очередь, используется для вставки в другие таблицы. В псевдокоде:

INSERT INTO TableFoo (Col2, Col3, Col4, etc.) VALUES (@Bla2, @bla3, @bla4);

Сразу после этой вставки я получаю последний идентификатор вставки:

SELECT last_insert_rowid() AS RowId;

Я получаю столбец RowId в хранилище данных и сохраняю его в int "RowId". Наконец, я вставляю еще несколько таблиц, таких как:

INSERT INTO TableBar (FooId, Col2) VALUES (RowId, @BSomeMoreBla)");

Вопрос : Если возможно, я хочу выполнить эту группу вставок (и RowId выбора) в 1 транзакции, чтобы предотвратить некоторые полусохраненные данные. Можно ли использовать транзакцию в этом сценарии и какой способ предпочтительнее?

Транзакция SQLite? Пространство имен System.Transaction на C #? Третий способ выполнения множественной вставки атомарной базы данных ...?

Ответы [ 2 ]

4 голосов
/ 07 декабря 2009

Рибер мне очень помог, но я нашел решение, которое искал сам. Для тех, кто может быть заинтересован, вот мой код (возможно, нужно немного настроить, но совершенно законный и пригодный для использования код):

пь. У tbl1 есть автоматическое увеличение PK, tbl2 и tbl3 зависит от PK tbl1 через FK. Если возникает исключение, ни один из запросов не фиксируется, как приличная транзакция должна вести себя ;-). Только если Commit () выполняется без ошибок, вся группа вставляется, даже если в середине пути есть SELECT.

try {
    transaction = connection.BeginTransaction();

    command = new SQLiteCommand();
    command.Transaction = transaction;
    command.CommandText = "INSERT INTO tbl1 (data) VALUES ('blargh')";
    command.ExecuteNonQuery();

    command = new SQLiteCommand();
    command.Transaction = transaction;
    command.CommandText = "SELECT last_insert_rowid()";
    rowId = Convert.ToInt64(command.ExecuteScalar());

    command = new SQLiteCommand();
    command.Transaction = transaction;
    command.CommandText = "INSERT INTO tbl2 (id, tbl1Id) VALUES (2, @rowId)";
    command.Parameters.Add(new SQLiteParameter("@rowId", rowId));
    command.ExecuteNonQuery();

    command = new SQLiteCommand();
    command.Transaction = transaction;
    command.CommandText = "INSERT INTO tbl3 (id, tbl1Id) VALUES (3, @rowId)";
    command.Parameters.Add(new SQLiteParameter("@rowId", rowId));
    command.ExecuteNonQuery();

    transaction.Commit();
}
catch (Exception ex) {
    if(connection.State == ConnectionState.Open)
        transaction.Rollback();
    MessageBox.Show(ex.Message);
}
finally {
    connection.Close();
    transaction.Dispose();
    command.Dispose();
}
2 голосов
/ 06 декабря 2009

Это должна быть транзакция SQLite. Лучше всего использовать такого поставщика данных Sqlite, как этот: http://sqlite.phxsoftware.com/ Я не уверен, что сам по себе базовый ADO.Net действительно будет работать правильно.

РЕДАКТИРОВАТЬ ДЛЯ КОММЕНТАРИИ:

Хорошо, вы просто хотите выполнить транзакцию, как и любую другую транзакцию ADO:

        SqliteCommand command = connection.CreateCommand();
        SqlTransaction transaction = null;

        connection.Open();

        transaction = connection.BeginTransaction();

        command.Transaction = transaction;

        command.CommandText = "Insert bla";
        command.ExecuteNonQuery();

        command.CommandText = "Update bla";
        command.ExecuteNonQuery();

        transaction.Commit();
        connection.Close();

Обычно вы также хотите поместить все это в попытку / отлов с откатом

Примечание: я не на 100% в этой команде SQlLite. Взгляните на свою документацию ... но остальное должно быть правильно

...