在C#中使用SQLite.NET获取最后一个插入ID

时间:2010-12-02 23:42:19

标签: c# sql sqlite

我有一个简单的问题,一个不那么简单的解决方案......我目前正在将一些数据插入到这样的数据库中:

                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);

最后一行非常重要。为什么我提供连接?那么有一个名为 last_insert_rowid()的SQLite函数,您可以调用它并获取最后一个插入ID。问题是它绑定到一个连接,.NET似乎重新打开并关闭每个数据集操作的连接。我以为从表适配器获取连接会改变一些事情。但事实并非如此。

有谁知道如何解决这个问题?也许从哪里获得持续的连接?或者更优雅的东西?

谢谢。

编辑:

这也是交易的问题,如果我想使用交易,我需要相同的连接,所以这也是一个问题......

8 个答案:

答案 0 :(得分:58)

对SQLite使用C#(。net 4.0),SQLiteConnection类的属性LastInsertRowId等于最近插入(或更新)元素的主要整数键。

如果表没有主整数键(在这种情况下,rowID是列自动创建),则返回rowID。

有关详情,请参阅https://www.sqlite.org/c3ref/last_insert_rowid.html

至于在单个事务中包装多个命令,在事务开始之后和提交之前输入的任何命令都是一个事务的一部分。

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

    ... [execute insert statement]

    rowID = con.LastInsertRowId;

    transaction.Commit()
}

答案 1 :(得分:46)

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.

答案 2 :(得分:7)

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();

答案 3 :(得分:1)

    database = new SQLiteConnection(databasePath);

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

答案 4 :(得分:1)

我正在使用Microsoft.Data.Sqlite包,但没有看到LastInsertRowId属性。但是您不必创建第二次数据库访问即可获取最后一个ID。而是将两个sql语句合并为一个字符串。

string sql = @"
    insert into MyTable values (null, @name);  
    select last_insert_rowid();";

using (var cmd = conn.CreateCommand()) {
    cmd.CommandText = sql;
    cmd.Parameters.Add("@name", SqliteType.Text).Value = "John";
    int lastId = Convert.ToInt32(cmd.ExecuteScalar());
}

答案 5 :(得分:0)

SQLiteConnection 对象具有该属性,因此不需要其他查询。 在INSERT之后,您只需使用用于INSERT命令的 SQLiteConnection 对象的 LastInsertRowId 属性。 LastInsertRowId 属性的类型为 Int64 。 当然,正如您现在所做的那样,要使自动递增工作,必须将表上的主键设置为 AUTOINCREMENT 字段,这是另一个主题。

答案 6 :(得分:0)

Microsoft引用和SQLite引用似乎都有答案,这就是有些人使LastInsertRowId属性起作用而其他人不起作用的原因。

我个人不使用PK,因为它只是rowid列的别名。使用rowid的速度大约是您创建的rowid的两倍。如果我有一个PK的TEXT列,我仍然使用rowid并使文本列唯一。 (仅适用于SQLite3。v1和v2需要您自己的,因为真空会更改行标识号)

也就是说,从最后插入的记录中获取信息的方法是下面的代码。由于该函数向自身进行了左连接,因此我只是为了提高速度而将其限制为1,即使您不这样做,主SELECT语句也将只有1条记录。

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

答案 7 :(得分:0)

# How about just running 2x SQL statements together using Execute Scalar?
# Person is a object that has an Id and Name property

var connString = LoadConnectionString(); // get connection string
using (var conn = new SQLiteConnection(connString)) // connect to sqlite
{

    // insert new record and get Id of inserted record
    var sql = @"INSERT INTO People (Name) VALUES (@Name);
                SELECT Id FROM People
                ORDER BY Id DESC";

    var lastId = conn.ExecuteScalar(sql, person);
}