SqlCommand(使用语句/释放问题)

10

接下来是一个例子...

        Using cn As New SqlConnection(ConnectionString)
            Try
                Dim cmd As SqlCommand = New SqlCommand
                With cmd
                    .Connection = cn
                    .Connection.Open()
                    .CommandText = "dbo.GetCustomerByID"
                    .CommandType = CommandType.StoredProcedure
                    .Parameters.Add("@CustomerID", SqlDbType.Int, 4)
                    .Parameters("@CustomerID").Value = CustomerID
                End With

                da = New SqlDataAdapter(cmd)
                da.Fill(ds, "Customer")
            Catch ex As Exception

            End Try
        End Using

根据我的研究,今天看起来基本上是可以的,但SqlCommand没有被处理。

问题->以下哪个示例是处理这个问题的最佳方法?

示例2-手动处理

        Using cn As New SqlConnection(ConnectionString)
            Try
                Dim cmd As SqlCommand = New SqlCommand
                With cmd
                    .Connection = cn
                    .Connection.Open()
                    .CommandText = "dbo.GetCustomerByID"
                    .CommandType = CommandType.StoredProcedure
                    .Parameters.Add("@CustomerID", SqlDbType.Int, 4)
                    .Parameters("@CustomerID").Value = CustomerID
                End With

                da = New SqlDataAdapter(cmd)
                cmd.Dispose()
                da.Fill(ds, "Customer")
            Catch ex As Exception

            End Try
        End Using

示例3 - 使用Using语句自动释放资源

        Using cn As New SqlConnection(ConnectionString)
            Try
                Using cmd As New SqlCommand
                    With cmd
                        .Connection = cn
                        .Connection.Open()
                        .CommandText = "dbo.GetCustomerByID"
                        .CommandType = CommandType.StoredProcedure
                        .Parameters.Add("@CustomerID", SqlDbType.Int, 4)
                        .Parameters("@CustomerID").Value = CustomerID
                    End With

                    da = New SqlDataAdapter(cmd)
                    da.Fill(ds, "Customer")
                End Using
            Catch ex As Exception

            End Try
        End Using

示例4 - 与示例3相同,但Try/Catch位于Using内部 - 这会有所不同吗?

        Using cn As New SqlConnection(ConnectionString)
            Using cmd As New SqlCommand
                Try
                    With cmd
                        .Connection = cn
                        .Connection.Open()
                        .CommandText = "dbo.GetCustomerByID"
                        .CommandType = CommandType.StoredProcedure
                        .Parameters.Add("@CustomerID", SqlDbType.Int, 4)
                        .Parameters("@CustomerID").Value = CustomerID
                    End With

                    da = New SqlDataAdapter(cmd)
                    da.Fill(ds, "Customer")
                Catch ex As Exception

                End Try
            End Using
        End Using

示例5 - 与示例4相同,但CommandText和cn在Using语句中指定 - 这样做有什么优势?

        Using cn As New SqlConnection(ConnectionString)
            Using cmd As New SqlCommand("GetCustomerByID", cn)
                Try
                    With cmd
                        .Connection.Open()
                        .CommandType = CommandType.StoredProcedure
                        .Parameters.Add("@CustomerID", SqlDbType.Int, 4)
                        .Parameters("@CustomerID").Value = CustomerID
                    End With

                    da = New SqlDataAdapter(cmd)
                    da.Fill(ds, "Customer")
                Catch ex As Exception

                End Try
            End Using
        End Using

示例6 - 与示例5相同,但连接是在cn上打开而不是cmd。如果只执行一个存储过程,是否最好在cmd上打开连接?

        Using cn As New SqlConnection(ConnectionString)
            cn.Open()

            Using cmd As New SqlCommand("GetCustomerByID", cn)
                Try
                    With cmd
                        .Connection = cn
                        .CommandType = CommandType.StoredProcedure
                        .Parameters.Add("@CustomerID", SqlDbType.Int, 4)
                        .Parameters("@CustomerID").Value = CustomerID
                    End With

                    da = New SqlDataAdapter(cmd)
                    da.Fill(ds, "Customer")
                Catch ex As Exception

                End Try
            End Using
        End Using

1
使用using语句更安全,但忽略所有异常的try/catch在大多数情况下是不被鼓励的。因此,您放置try catch的方式和位置取决于您想要实现什么目标。您有什么问题? - Steven Doggart
这个问题对我来说更适合在codereview.stackexchange.com上进行。 - Sam Axe
空的try/catch只是一个例子,但在这种情况下,它只是为了安全起见而存在。在该过程之外,我将检查数据集是否包含任何表格。如果没有,我会适当处理。关于问题,它在顶部 - 我问什么是处理SqlCommand的处置的最佳方法。我个人认为示例5是正确的,但想知道其他人的反馈。 - cw_dev
@Dan-o - 抱歉,我不知道codereview.stackexchange.com。如果需要的话,我可以删除这个问题。 - cw_dev
1
不,这是我们业务需求的一个严肃问题。今天我们一直在尝试解决连接池问题,最终只能在我们的SqlConnection上添加Using。在这样做的过程中,我想知道是否需要在SqlCommand上执行相同的操作。如果您查看我的先前问题,您会发现这些不是“家庭作业”任务。 - cw_dev
显示剩余2条评论
1个回答

10
DataAdapter.Fill命令将自行打开和关闭连接,因此您不需要cmd.Connection.Open()。(参考:http://msdn.microsoft.com/en-us/library/377a8x4t.aspx中的备注部分。)
对于SqlConnection,使用Using语句会在您的代码中调用.Close
变量cmd一旦超出作用域(或更早地由.NET确定不再使用),就可以进行垃圾回收。
在您的第2个示例中,我不确定在DataAdapter使用cmd之前处置cmd是否是一个好主意。

[用户“JefBar软件服务”在我是否应该在SQLCommand对象上调用Dispose?中提供的信息] 在撰写本文时,在SqlCommand上调用.Dispose没有任何效果,因为在其构造函数中有代码

public SqlCommand() : base() {
    GC.SuppressFinalize(this);
}

1
谢谢。我不知道关于数据适配器的那个,所以会相应地进行修改。所以,如果该项变得可以进行垃圾回收,您是说Using语句并不是真正必要的吗? - cw_dev
@cw_dev 我编辑了我的答案,特别是关于如何处理 SqlCommand 的释放。 - Andrew Morton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接