重构DAL代码以支持存储过程

zSy*_*sis 0 c# refactoring data-access-layer

    private static readonly string dataProvider = ConfigurationManager.AppSettings.Get("Provider");
    private static readonly DbProviderFactory factory = DbProviderFactories.GetFactory(dataProvider);
    private static readonly string connectionString = ConfigurationManager.ConnectionStrings[dataProvider].ConnectionString;
    /// <summary>
    /// Executes Update statements in the database.
    /// </summary>
    /// <param name="sql">Sql statement.</param>
    /// <returns>Number of rows affected.</returns>
    public static int Update(string sql)
    {
        using (DbConnection connection = factory.CreateConnection())
        {
            connection.ConnectionString = connectionString;

            using (DbCommand command = factory.CreateCommand())
            {
                command.Connection = connection;
                command.CommandText = sql;

                connection.Open();
                return command.ExecuteNonQuery();
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

我需要帮助重写这个,以便它可以使用存储过程.(通过sproc名称和params)有没有人知道我应该怎么做呢?编辑:我遇到问题的区域是试图找出填写参数的方法.

谢谢

Joh*_*ers 10

您已经需要参数,而不管您是否正在实现存储过程.

现在,您的代码可以通过查询来调用SELECT * FROM Table WHERE ID = @ID,在这种情况下,您已经需要传递一个Dictionary<string,object> params.让您的代码填写您已有命令的Parameters集合,并在担心存储过程之前对其进行测试.

一旦工作,你应该简单地创建一个重载,接受一个bool,说这是一个存储过程,然后用它来设置命令的CommandType属性.


编辑:这是我将如何重构它

第1步:概括更新

除了名称之外,Update方法没有任何特殊之处可以阻止它用于其他非查询操作.所以:

    /// <summary>
    /// Executes Update statements in the database.
    /// </summary>
    /// <param name="sql">Sql statement.</param>
    /// <returns>Number of rows affected.</returns>
    public static int Update(string sql)
    {
        return NonQuery(sql);
    }

    public static int NonQuery(string sql)
    {
        using (DbConnection connection = factory.CreateConnection())
        {
            connection.ConnectionString = connectionString;

            using (DbCommand command = factory.CreateCommand())
            {
                command.Connection = connection;
                command.CommandText = sql;

                connection.Open();
                return command.ExecuteNonQuery();
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

第2步:参数怎么样?

您当前的代码甚至无法处理使用参数的UPDATE查询,所以让我们开始修复它.首先,如果没有指定参数,请确保它仍然有效:

    public static int NonQuery(string sql)
    {
        Dictionary<string, object> parameters = null;

        if (parameters == null)
        {
            parameters = new Dictionary<string, object>();
        }

        using (DbConnection connection = factory.CreateConnection())
        {
            connection.ConnectionString = connectionString;

            using (DbCommand command = factory.CreateCommand())
            {
                command.Connection = connection;
                command.CommandText = sql;

                foreach (KeyValuePair<string, object> p in parameters)
                {
                    var parameter = command.CreateParameter();
                    parameter.ParameterName = p.Key;
                    parameter.Value = p.Value;

                    command.Parameters.Add(parameter);
                }

                connection.Open();
                return command.ExecuteNonQuery();
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

一旦有效,将参数提升为参数.这不会影响任何现有的呼叫者Update:

    /// <summary>
    /// Executes Update statements in the database.
    /// </summary>
    /// <param name="sql">Sql statement.</param>
    /// <returns>Number of rows affected.</returns>
    public static int Update(string sql)
    {
        return NonQuery(sql, null);
    }

    public static int NonQuery(string sql, Dictionary<string, object> parameters)
Run Code Online (Sandbox Code Playgroud)

此时,使用参数化查询测试NonQuery.一旦有效,创建一个接受参数的Update重载:

    /// <summary>
    /// Executes Update statements in the database.
    /// </summary>
    /// <param name="sql">Sql statement.</param>
    /// <returns>Number of rows affected.</returns>
    public static int Update(string sql)
    {
        return NonQuery(sql, null);
    }

    /// <summary>
    /// Executes Update statements in the database.
    /// </summary>
    /// <param name="sql">Sql statement.</param>
    /// <param name="parameters">Name/value dictionary of parameters</param>
    /// <returns>Number of rows affected.</returns>
    public static int Update(string sql, Dictionary<string, object> parameters)
    {
        return NonQuery(sql, parameters);
    }
Run Code Online (Sandbox Code Playgroud)

第3步:考虑存储过程

在如何处理存储过程方面没有什么区别.您已经得到的内容隐含如下:

            using (DbCommand command = factory.CreateCommand())
            {
                command.Connection = connection;
                command.CommandText = sql;
                command.CommandType = CommandType.Text;
Run Code Online (Sandbox Code Playgroud)

因此,请使用CommandType.Text并将其提升为重载中的参数:

    public static int NonQuery(string sql, Dictionary<string, object> parameters)
    {
        return NonQuery(sql, CommandType.Text, parameters);
    }

    public static int NonQuery(string sql, CommandType commandType, Dictionary<string, object> parameters)
Run Code Online (Sandbox Code Playgroud)

最后,如果您愿意,请更新Update:

    /// <summary>
    /// Executes Update statements in the database.
    /// </summary>
    /// <param name="sql">Sql statement.</param>
    /// <param name="parameters">Name/value dictionary of parameters</param>
    /// <returns>Number of rows affected.</returns>
    public static int Update(string sql, Dictionary<string, object> parameters)
    {
        return Update(sql, CommandType.Text, parameters);
    }

    /// <summary>
    /// Executes Update statements in the database.
    /// </summary>
    /// <param name="sql">Sql statement.</param>
    /// <param name="commandType">CommandType.Text or CommandType.StoredProcedure</param>
    /// <param name="parameters">Name/value dictionary of parameters</param>
    /// <returns>Number of rows affected.</returns>
    public static int Update(string sql, CommandType commandType, Dictionary<string, object> parameters)
    {
        return NonQuery(sql, parameters);
    }
Run Code Online (Sandbox Code Playgroud)

当然,作为读者的最后练习,您可以使用对NonQuery的调用替换所有Update调用,并完全删除Update.


当然,这种简单的技术不处理输出参数,或者需要指定参数的DbType的情况.为此,您需要接受某种ParameterCollection.