web-dev-qa-db-ja.com

C#でSQLite.NETを使用して最後の挿入IDを取得する

私はそれほど単純ではない解決策で単純な問題を抱えています...現在、次のようにデータベースにデータを挿入しています:

                kompenzacijeDataSet.KompenzacijeRow kompenzacija = kompenzacijeDataSet.Kompenzacije.NewKompenzacijeRow();
                kompenzacija.Datum = DateTime.Now;
                kompenzacija.PodjetjeID = stranka.id;
                kompenzacija.Znesek = Decimal.Parse(tbZnesek.Text);

                kompenzacijeDataSet.Kompenzacije.Rows.Add(kompenzacija);

                kompenzacijeDataSetTableAdapters.KompenzacijeTableAdapter kompTA = new kompenzacijeDataSetTableAdapters.KompenzacijeTableAdapter();
                kompTA.Update(this.kompenzacijeDataSet.Kompenzacije);

                this.currentKompenzacijaID = LastInsertID(kompTA.Connection);

最後の行は重要です。なぜ接続を提供するのですか?さて、呼び出すSQLite関数last_insert_rowid()を呼び出して、最後の挿入IDを取得できます。問題は、それが接続にバインドされており、.NETがデータセット操作ごとに接続を再オープンおよびクローズしているように見えることです。テーブルアダプターから接続を取得すると、状況が変わると思いました。しかし、そうではありません。

誰かがこれを解決する方法を知っていますか?多分どこから恒常的な接続を得るのですか?それとももっとエレガントなものでしょうか?

ありがとうございました。

編集:

これもトランザクションの問題です。トランザクションを使用する場合も同じ接続が必要なので、これも問題です...

23
vanneto
select last_insert_rowid();

そして、それをスカラークエリとして実行する必要があります。

string sql = @"select last_insert_rowid()";
long lastId = (long)command.ExecuteScalar(sql); // Need to type-cast since `ExecuteScalar` returns an object.
49

SQLiteでC#(.net 4.0)を使用すると、SQLiteConnectionクラスには、最後に挿入(または更新)された要素のプライマリ整数キーと等しいプロパティLastInsertRowIdがあります。

テーブルに主整数キーがない場合、rowIDが返されます(この場合、rowIDは列が自動的に作成されます)。

詳細は https://www.sqlite.org/c3ref/last_insert_rowid.html を参照してください。

1つのトランザクションで複数のコマンドをラップする場合と同様に、トランザクションが開始してからコミットされるまでに入力されたコマンドは、1つのトランザクションの一部です。

long rowID;
using (SQLiteConnection con = new SQLiteConnection([datasource])
{
    SQLiteTransaction transaction = null;
    transaction = con.BeginTransaction();

    ... [execute insert statement]

    rowID = con.LastInsertRowId;

    transaction.Commit()
}
67
Alex Smith

last_insert_rowid()はソリューションの一部です。実際のIDではなく、行番号を返します。

cmd = CNN.CreateCommand();
cmd.CommandText = "SELECT last_insert_rowid()";
object i = cmd.ExecuteScalar();

cmd.CommandText = "SELECT " + ID_Name + " FROM " + TableName + " WHERE rowid=" + i.ToString();
i = cmd.ExecuteScalar();
7
Greg Carrier
    database = new SQLiteConnection(databasePath);

    public int GetLastInsertId()
    {
        return (int)SQLite3.LastInsertRowid(database.Handle);
    }

SQLiteConnectionオブジェクトにはそのためのプロパティがあるため、追加のクエリは必要ありません。 INSERTの後、あなたは私の使っていたLastInsertRowIdプロパティSQLiteConnectionオブジェクトのINSERTコマンドに使用されます。 LastInsertRowIdプロパティのタイプはInt64です。もちろん、既に行ったように、自動インクリメントが機能するためには、テーブルの主キーを[〜#〜] autoincrement [〜#〜]フィールドに設定する必要があります。これは別のトピックです。

1
stonito

MicrosoftのリファレンスとSQLiteのリファレンスの両方に対する回答があるようで、LastInsertRowIdプロパティを機能させる人もいればそうでない人もいます。

個人的には、PKはROWID列の単なるエイリアスであるため使用しません。 ROWIDの使用は、作成したものの約2倍の速さです。 PKのTEXT列がある場合でも、ROWIDを使用して、テキスト列を一意にします。 (SQLite 3のみ。バキュームによってROWID番号が変更されるため、v1とv2には独自のものが必要です)

つまり、最後の挿入でレコードから情報を取得する方法は、以下のコードです。関数はそれ自体に左結合を行うので、速度を上げるために、それを1に制限します。そうしない場合でも、メインのSELECTステートメントからのレコードは1つだけです。

SELECT my_primary_key_column FROM my_table
WHERE rowid in (SELECT last_insert_rowid() LIMIT 1);
0
Jym