您是否应该重复使用 SqlConnection、SqlDataAdapter 和 SqlCommand 对象?

8

我正在使用一个类似于以下代码的布局编写的DAL对象。我简化了很多代码,只是为了展示设置。

public class UserDatabase : IDisposable
{
    private SqlDataAdapter UserDbAdapter;
    private SqlCommand UserSelectCommand;
    private SqlCommand UserInsertCommand;
    private SqlCommand UserUpdateCommand;
    private SqlCommand UserDeleteCommand;

    private System.Data.SqlClient.SqlConnection SQLConnection; 

    public UserDatabase()
    {
        this.SQLConnection = new System.Data.SqlClient.SqlConnection(ConnectionString);
        this.UserDbAdapter= new SqlDataAdapter(); 
        this.UserDbAdapter.DeleteCommand = this.UserDeleteCommand;
        this.UserDbAdapter.InsertCommand = this.UserInsertCommand;
        this.UserDbAdapter.SelectCommand = this.UserSelectCommand;
        this.UserDbAdapter.UpdateCommand = this.UserUpdateCommand;
    }

    private bool FillUsers(DataSet UserDataSet, out int numberOfRecords)
    {
        bool success = true;

        numberOfRecords = 0;
        string errorMsg = null;

        this.UserDbAdapter.SelectCommand = this.GetUsersSelectCommand();

        numberOfRecords = UserDbAdapter.Fill(UserDataSet, UsersTableName);

        return success;
    }

    private SqlCommand GetUserSelectCommand()
    {
        if (this.UserSelectCommand==null)
            this.UserSelectCommand= new System.Data.SqlClient.SqlCommand();
        this.UserSelectCommand.CommandText = "dbo.Users_Select";
        this.UserSelectCommand.CommandType = System.Data.CommandType.StoredProcedure;
        this.UserSelectCommand.Connection = this.SQLConnection;
        this.UserSelectCommand.Parameters.Clear();
        this.UserSelectCommand.Parameters.AddRange(new System.Data.SqlClient.SqlParameter[] {
        new System.Data.SqlClient.SqlParameter("@RETURN_VALUE", System.Data.SqlDbType.Variant, 0, System.Data.ParameterDirection.ReturnValue, false, ((byte)(0)), ((byte)(0)), "", System.Data.DataRowVersion.Current, null)});

        return UserSelectCommand;
    }

还有其他多个填充类型函数,它们都是以相同的方式重用Connection对象、SqlCommands和SqlDataAdapter编写的。SqlDataAdapter在内部管理SqlConnection的打开和关闭。

所以我的问题有几个方面。这种设计是否不好?如果是,为什么?

如果不好,是否应该改为像以下代码一样保持更本地的范围:

    public bool FillUsers(DataSet UserDataSet)
    {
        using (SqlConnection conn = new SqlConnection(ConnectionString))
        {
            using (SqlCommand command = GetUsersSelectCommand())
            {
                using (SqlDataAdapter adapter = new SqlDataAdapter(command, conn))
                {
                    adapter.Fill(UserDataSet, UsersTableName);
                }
            }
        }
    }

这需要对所有函数进行操作,似乎创建、处理和重新制作比保留项目更糟糕。然而,这似乎是我在网上看到的设置。


你是否测量了性能问题,以至于你感到需要进行优化?数据库连接是按设计进行池化的。没有必要过度“重新池化”。 - spender
我几年前问过一个类似的问题:https://dev59.com/qXVC5IYBdhLWcg3wpS3f - spender
没有性能问题的关联。我正在启动一个新项目,需要一个数据访问对象,并且想知道这是否是“正确”的方法,或者是否有更好的方法。 - Equixor
1个回答

8

不,这没有任何问题。当您完成使用实现IDisposable的对象时,应立即处理它们。

给定一个SqlConnection,当您处理连接时,底层连接将简单地返回到池中。 它并不一定像您想象的那样“关闭”。 最好让连接池做它的工作。 这里是ADO.NET连接池的MSDN链接。试图使其执行它未设计的任务(有些人称之为优化,令人惊讶)通常是进入兔子洞的旅程。

此外,在尝试优化之前,请确保您已经测量和观察到了问题。(我并不是以严厉的方式说这句话,只是为了节省您的时间。)


顶部代码在UserDatabase对象被处理之前不会处理任何对象。因此,似乎重复使用它们会违反这种设计实践? - Equixor
@Equixor:我更具体地指的是SqlConnection。你的类名UserDatabase有点误导人,因为它并不是一个实际的数据库。也许你可以创建一个名为GetUsers()的方法,它将返回用户列表。你的第二个代码贴子是正确的。保留它们会更糟糕(有时会导致难以重现的错误)。 - Bryan Crosby
好的,谢谢。我相信这个整体设计也可以改进。我们拥有的大多数DAL类都是这样的,它们填充数据集,然后由BLL使用。 - Equixor

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