运行两个实例时自动递增不正确

时间:2019-09-26 12:34:43

标签: .net vb.net sqlite system.data.sqlite

我正在运行下面的代码的2个实例,它们连接到System.Data.SQLite数据库。当我使用任一实例将行插入数据库时​​,从其他实例读取时,自动递增的值(ID)不合适。这是什么原因造成的?

Imports System.Data.SQLite
Public Class Form1
    Public cnn As SQLiteConnection
    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        cnn = New SQLiteConnection("Data Source=\\abc\xx\x_backup.db;Password=password;Connect Timeout=55;FailIfMissing=True")
        cnn.ParseViaFramework = True
        cnn.Open()
    End Sub
    Public Function inserttoTable(ByVal sql As String) As DataTable

         Try
            sql = "SELECT max(ID) FROM joblog;"
            Dim mycommand As SQLiteCommand = New SQLiteCommand(cnn)
            mycommand.CommandText = sql
            MsgBox(mycommand.ExecuteScalar)
            sql = "INSERT INTO joblog (jobid) VALUES (123);"

            mycommand = New SQLiteCommand(cnn)
            mycommand.CommandText = sql
            MsgBox(mycommand.ExecuteNonQuery())
        Catch ex As Exception
            MsgBox(ex.ToString)
        End Try

3 个答案:

答案 0 :(得分:0)

  

当我使用任一实例将行插入数据库时​​,从其他实例读取时自动递增的值(ID)不正确

怀疑是因为您的连接和命令没有关闭/布置,所以它们保持打开状态。

连接的最佳建议是先使用它,然后关闭/处置它。命令也一样,请确保将它们丢弃。

这是执行此操作的一种方法:

 Dim intReturn As Integer
 sql = "SELECT max(ID) FROM joblog;"

 ' First query to get your scalar return value
 Using cnn As New New SQLiteConnection("Data Source=\\abc\xx\x_backup.db;Password=password;Connect Timeout=55;FailIfMissing=True")
    Using mycommand As New SQLiteCommand(sql, cnn)
       cnn.ParseViaFramework = True
       cnn.Open()

       intReturn = mycommand.ExecuteScalar
       MessageBox.Show(intReturn)

    End Using
 End Using

 ' Second query to actually do the insert
 sql = "INSERT INTO joblog (jobid) VALUES (123);"
 Using cnn As New New SQLiteConnection("Data Source=\\abc\xx\x_backup.db;Password=password;Connect Timeout=55;FailIfMissing=True")
    Using mycommand As New SQLiteCommand(sql, cnn)
       cnn.ParseViaFramework = True
       cnn.Open()

       intReturn = mycommand.ExecuteNonQuery()
       MessageBox.Show("Records affected " & intReturn)

    End Using
 End Using

另一方面,请考虑使用SQL Parameters,否则您可能容易受到SQL注入攻击。

答案 1 :(得分:0)

我使用的函数在某种程度上等效于Sql Server中的Scope_Identity。我没有SqLite数据库,所以无法测试。我不确定是否可以在SqLite中链接命令,但是如果不能,则只进行2个单独的查询。 ExecuteScalar返回结果集中第一行的第一列,即您想要的数字。

Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    Dim NewID As Long
    Using cn As New SQLiteConnection("Your connection string")
        Using cmd As New SQLiteCommand("INSERT INTO joblog (jobid) VALUES (123); Select last_insert_rowid()")
            NewID = CLng(cmd.ExecuteScalar())
        End Using
    End Using
    MessageBox.Show($"The new ID is {NewID}")
End Sub

答案 2 :(得分:0)

一个简单的答案是您不应该使用共享的sqlite数据库文件,它不稳定并且数据库文件很容易损坏。使用mariadb / postgresql是一个更好的主意。

我认为您的问题与交易有关,您应该手动提交更改以在更新后立即更新数据库文件。

1. SQLiteTransaction trans = conn.BeginTransaction();
2. select max(id), insert...
3. trans.commit();