【问题标题】:Trying to run 2 queries in one connection尝试在一个连接中运行 2 个查询
【发布时间】:2020-09-16 13:07:22
【问题描述】:

我尝试运行一小段代码,我首先检查该值是否存在,如果不存在则更新我的数据库。我的问题是我可以运行一个查询或另一个但不能同时运行,因为它表明数据库已打开且无法访问。我确定我可以写入数据库。它不受读保护,位于我无法访问的位置等。如果我只是尝试更新而不检查,则例程运行。检查肯定没有记录。我已经尝试使用完全不同的变量进行连接的单独例程。我很难过。我尝试过关闭、使用、处置,但我需要比我聪明得多的人来告诉我我做错了什么......

For Each strfile As String In flist
    Dim pth As String = Path.GetDirectoryName(strfile)
    Dim objReader As New System.IO.StreamReader(strfile)
    Dim dVal As String = String.Empty
    TextLine = objReader.ReadLine()
    SplitLine = Split(TextLine, ",")
    dVal = SplitLine(1)

    Using Dcon As New OleDbConnection
        Dcon.ConnectionString = dbProvider
        Dcon.Open()

        Dim q1 As String = "SELECT Shares.[_Date] FROM Shares WHERE (((Shares.[_Date])=" & dVal & "))"
        Dim comd As OleDbCommand = New OleDbCommand(q1, Dcon)
        comd.ExecuteReader()

        Dim q2 As String = "INSERT INTO Shares (Code, _Date, _Open, _High, _Low, _Close, _Volume) " &
                                                                  "SELECT F1, F2, F3, F4, F5, F6, F7 FROM [Text;HDR=NO;DATABASE=" & pth & "].[" & Path.GetFileName(strfile) & "];"

        Dim cmd As OleDbCommand = New OleDbCommand(q2, Dcon)

        cmd.ExecuteNonQuery()
        Dcon.Close()
    End Using
Next

我尝试过单独的例程,我尝试过打开、关闭然后重新打开。我尝试了一种连接,我尝试了两种。有谁知道我做错了什么,为什么它一直告诉我数据库是专门打开的,为什么它不让我写信?

提前感谢那些提供帮助的人。

【问题讨论】:

  • 你真的应该为事物使用更好的名字。使用comdcmd 区分两个命令对象是一种很好的混淆方式。描述性名称怎么样,例如selectCommandinsertCommand?

标签: sql database vb.net


【解决方案1】:

感谢大家的帮助,但在凌晨 2 点,我顿悟了,意识到问题不在于数据库。

我让流式阅读器保持打开状态,这就是导致问题的原因。

不过,我已经接受了你们的 cmets,并感谢在开发更好的代码方面提供的帮助。

【讨论】:

    【解决方案2】:

    我在尝试执行多个 sql 语句时使用此代码:

    Dim ConnectionString As String = ("Connection_String")
            'LoginsVal is a Table,
            Dim SqlStr1 As String = ("Select Count(Accounts.DtCrtd) FROM Accounts WHERE Accounts.DtCrtd > " & Now.Date & ";")
            Dim SqlStr2 As String = ("INSERT INTO LoginsVal(LoginNm,DtMdfd) VALUES ('Test1'," & Now.Date & ");")
            'DtCtrtd is Date DataType, Accounts is the Table Name
            Dim ThisCmd1, ThisCmd2 As New OleDbCommand
            Using ThisConn As New OleDbConnection With {.ConnectionString = ConnectionString}
                ThisConn.Open() 'Open connection
                With ThisCmd1
                    .Connection = ThisConn
                    .CommandType = CommandType.Text
                    .CommandText = SqlStr1
                End With
                'Debug.WriteLine(ThisCmd1.ExecuteScalar) 'use to test only without if statement below.
                If Convert.ToInt32(ThisCmd1.ExecuteScalar) <= 0 Then
                    Debug.WriteLine("No records found")
                Else
                    'Your Next SqlStatement
                    With ThisCmd2
                        .Connection = ThisConn
                        .CommandType = CommandType.Text
                        .CommandText = SqlStr2
                    End With
                    Debug.WriteLine("Num of Rows affects is : " & ThisCmd2.ExecuteNonQuery)
                End If
                ThisCmd1.Dispose()
                ThisCmd2.Dispose()
                ThisConn.Close() 'Close connection
            End Using
    

    【讨论】:

    • 如果数据库对象公开了 .Dispose 方法,则需要调用它。这适用于连接和命令。使用使用块。为什么要检查之前在线路上创建的连接的状态。您不需要 with 语法。您可以将连接字符串直接传递给连接的构造函数。您正在执行每个命令两次! .ExecuteScalar 返回一个对象。不能写,因为它不是字符串,也不能和 0 比较,因为它不是数字。
    • 对不起,我没有安静地跟着你,1)你说“如果数据库对象公开了一个 .Dispose 方法,它需要被调用”。你为什么这样?它与我的代码有什么关系? 2)你为什么要检查你刚刚在这个连接的线路上创建的连接的状态......我已经将连接字符串直接传递给构造函数,又怎么了? 3)您正在执行每个命令两次.......数字。我如何准确地执行每个命令两次?是的,你是对的 Debug.writeLine() 行'在提交答案之前忘记省略'谢谢
    • 关于 executeScalar(是的,但我的代码中唯一的错误是 'stackoverflow.com/questions/1999020/…)跨度>
    • 1.) 需要调用 .Dispose 方法,因为这些对象可能正在使用在 .Dispose 方法中释放的非托管资源。 2.) `使用 ThisConn 作为 New OleDbConnection(ConnectionString) 更短。不需要检查状态。
    • Count() 不返回 DbNull。它总是有价值的。
    【解决方案3】:

    实际的错误消息会告诉您连接上已经有一个打开的阅读器。显而易见的解决方案是关闭您打开的数据读取器。

    您的代码存在一些严重问题。您致电ExecuteReader,这就是打开阻止您的第二个命令的数据读取器的原因,但您实际上从未对该数据读取器执行任何操作。您没有将其分配给变量,因此您无法从中获取数据,也无法关闭它。你可以这样做:

    Dim reader = comd.ExecuteReader()
    
    'Use reader here.
    
    reader.Close()
    

    不过,正确的方法是使用 Using 块:

    Using reader = comd.ExecuteReader()
        'Use reader here.
    End Using
    

    也就是说,如果您要做的只是确定数据是否存在而不实际使用该数据,那么您根本不需要数据读取器。只需使用返回Boolean 的查询并调用ExecuteScalar,例如

    Using connection As New OleDbConnection("connection string here")
        connection.Open()
    
        Dim query As New OleDbCommand("SELECT COUNT(*) > 0 FROM MyTable", connection)
    
        If CBool(query.ExecuteScalar()) Then
            'The table does contain data.
        End If
    End Using
    

    您可以使用更高效的查询,具体取决于数据库。

    【讨论】:

      猜你喜欢
      • 2021-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-04
      • 1970-01-01
      • 2014-07-27
      • 2015-01-27
      • 1970-01-01
      相关资源
      最近更新 更多