处理 ClientInsertServerInsert 同步冲突时出现 SQL 命令“超时”异常

Posted

技术标签:

【中文标题】处理 ClientInsertServerInsert 同步冲突时出现 SQL 命令“超时”异常【英文标题】:SQL Command "Timeout expired" Exception while handling ClientInsertServerInsert sync conflict 【发布时间】:2012-06-04 07:55:09 【问题描述】:

我正在使用 VS 2010 同步 2 个数据库(SQL Express 和 SQL Compact Edition)。程序首次运行时它运行良好。但是,当代码执行多次时,会出现 SQL 命令“超时”异常。错误信息是:

超时。在操作完成之前超时时间已过或服务器没有响应。

以下是我处理ClientInsertServerInsert 冲突的代码。 (编辑:根据这篇 MSDN 文章,这与客户端和服务器都插入具有相同主键值的行有关。这会导致主键冲突。)

    Dim conflictTableName As String = e.TableMetadata.TableName.ToString
    Dim serverConflictDT, clientConflictDT As DataTable
    Dim clientConflictID As Int16
    Dim new_ID As Int16
    Dim SqlCon As New SqlConnection
    clientConflictDT = e.Conflict.ClientChange
    serverConflictDT = e.Conflict.ServerChange

    If e.Conflict.ConflictType = ConflictType.ClientInsertServerInsert Then
        SqlCon = New SqlConnection(STR_SQL_CON)

        Using SqlCon
            If SqlCon.State = ConnectionState.Closed Then SqlCon.Open()
            MsgBox(SqlCon.PacketSize.ToString & vbNewLine & conflictTableName.ToString)
            Dim sqlStr = "SELECT CASE WHEN MAX(ID) IS NULL THEN 0 ELSE MAX(ID)+1 END               FROM " & conflictTableName

            Dim sqlcmd As New SqlCommand(sqlStr, SqlCon)
            sqlcmd.CommandTimeout = 2

            new_ID = sqlcmd.ExecuteScalar  '<- This is the line where the Exception occurred

            clientConflictID = clientConflictDT.Rows(0)(0)

            MsgBox(new_ID.ToString & conflictTableName.ToString)

            Try
                Using SqlCeCon As New SqlCeConnection(STR_SQLCE_CON)
                    If SqlCeCon.State = ConnectionState.Closed Then SqlCeCon.Open()

                    Dim sqlCeCmd As New SqlCeCommand
                    Dim sqlCeStr = Nothing

                    sqlCeStr = "SELECT CASE WHEN MAX(ID) IS NULL THEN 0 ELSE MAX(ID)+1 END FROM " & conflictTableName
                    sqlCeCmd = New SqlCeCommand(sqlCeStr, SqlCeCon)
                    If new_ID < sqlCeCmd.ExecuteScalar Then
                        new_ID = sqlCeCmd.ExecuteScalar
                    End If

                    sqlCeStr = "UPDATE " & conflictTableName & " SET id=" & new_ID & " WHERE id=" & clientConflictID
                    sqlCeCmd.CommandText = sqlCeStr
                    sqlCeCmd.ExecuteNonQuery()
                End Using
            Catch ex As Exception

            Finally

            End Try

        End Using


    End If

提前致谢

【问题讨论】:

增加 commandtimeout 属性值。 我尝试将超时值更改为 0,但仍然无法继续 你是在使用 SQL 精简版的链接服务器吗?共享用于连接两个 sql server 的连接字符串。您遇到问题的代码行。修改sql精简版命令的commandtimeout。 sqlprofiler 来跟踪哪些值导致了问题?是导致主键违规还是命令超时? 【参考方案1】:

我想这是由数据库锁引起的。在我从

修改 SQL SELECT 语句之后
"SELECT CASE WHEN MAX(ID) IS NULL THEN 0 ELSE MAX(ID)+1 END FROM " & conflictTableName 

"SELECT CASE WHEN MAX(ID) IS NULL THEN 0 ELSE MAX(ID)+1 END FROM " & conflictTableName & " WITH (NOLOCK)"

那么问题就解决了。

无论如何,感谢所有 cmets :-)

【讨论】:

以上是关于处理 ClientInsertServerInsert 同步冲突时出现 SQL 命令“超时”异常的主要内容,如果未能解决你的问题,请参考以下文章

自然语言处理_一般处理流程

怎么在批处理中加回车命令?

throws关键字_异常处理的第一种方式(交给别人处理)和try_catch_异常处理的第二种方式(自己处理)

PHP异常处理

协处理器,王明学learn

批处理学习笔记第一课:什么是批处理