编写更优化的代码并在 C# 中重用代码

本文关键字:代码 优化 | 更新日期: 2023-09-27 17:55:26

我正在使用C# winforms和MSSQL server 2012编写桌面应用程序。 此应用程序中有几个类退出需要连接到数据库和所有 UINN ADO.Net。 这是我的类:

  class Prices
{
    private int id = 0;
    public int Id
    {
        get { return id; }
        set { id = value; }
    }
    private string materialName = string.Empty;
    ......
    ......
    ......
     public void updateMaterialPrice()
    {                        
            string conString = ConfigurationManager.ConnectionStrings["secaloFormulaCS"].ToString();
            using (SqlConnection sqlCon = new SqlConnection(conString))
            using (SqlCommand sqlCmd = new SqlCommand("spUpdateMaterialPrice", sqlCon))
            {
                sqlCmd.CommandType = CommandType.StoredProcedure;
                sqlCmd.Parameters.AddWithValue("materialName",MaterialName);
                sqlCmd.Parameters.AddWithValue("unitPrice", Price);
                sqlCmd.Parameters.AddWithValue("carbohydrate", Carbohydrtate);
                sqlCmd.Parameters.AddWithValue("protein", Proterin);
                sqlCmd.Parameters.AddWithValue("fat", Fat);
                sqlCmd.Parameters.AddWithValue("humidity", Humadity);
                sqlCmd.Parameters.AddWithValue("minerlas", Minerlas);
                sqlCon.Open();
                sqlCmd.ExecuteNonQuery();
                sqlCon.Close();
                sqlCon.Dispose();
            }                                                   
    }         
    public void addMaterial()
    {
        string ConString = ConfigurationManager.ConnectionStrings["secaloFormulaCS"].ToString(); 
        using(SqlConnection sqlCon = new SqlConnection(ConString))
        using(SqlCommand sqlCmd = new SqlCommand("spAddMaterial",sqlCon))
        {
            sqlCmd.CommandType = CommandType.StoredProcedure;
            sqlCmd.Parameters.AddWithValue("materialName", MaterialName); 
            sqlCmd.Parameters.AddWithValue("unitPrice",Price);
            sqlCmd.Parameters.AddWithValue("carbohydrate",Carbohydrtate);
            sqlCmd.Parameters.AddWithValue("proterin", Proterin); 
            sqlCmd.Parameters.AddWithValue("fat",Fat); 
            sqlCmd.Parameters.AddWithValue("humidity", Humadity); 
            sqlCmd.Parameters.AddWithValue("minerals",Minerlas);
            sqlCon.Open();
            sqlCmd.ExecuteNonQuery();
            sqlCon.Close();
            sqlCon.Dispose(); 
        }

正如您在addMterial()和updateMaterialPrice()中看到的那样,我使用相同的代码连接到数据库并调用存储过程,并且在我的其他类中重复了几次。 如何防止此代码重复? 有没有办法只编写连接所需的代码并查询数据库一次,然后根据需要多次重用?

编写更优化的代码并在 C# 中重用代码

我对数据库连接使用工厂模式,这意味着我永远不必打开 SqlConnection 或在程序中传递连接字符串。

下面是我用于运行返回多行的查询的方法的示例。

我会从"makeObject"方法调用该方法,该方法会将此数据表转换为对象。

public static class DB
{
    private static readonly string connectionString   = ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;
    private static readonly DbProviderFactory factory = DbProviderFactories.GetFactory("System.Data.SqlClient");
    /// <summary>
    /// Use when returning data from multiple rows
    /// </summary>
    /// <param name="sql">query</param>
    /// <param name="parameters">declared parameters</param>
    /// <returns>datatable of db rows</returns>
    public static DataTable GetDataTable(string sql, SqlParameter[] parameters)
    {
        try
        {
            using (DbConnection connection = factory.CreateConnection())
            {
                connection.ConnectionString = connectionString;
                using (DbCommand command = factory.CreateCommand())
                {
                    command.Connection  = connection;
                    command.CommandType = CommandType.Text;
                    command.CommandText = sql;
                    if (parameters != null)
                    {
                        foreach (var parameter in parameters)
                        {
                            if (parameter != null)
                                command.Parameters.Add(parameter);
                        }
                    }
                    using (DbDataAdapter adapter = factory.CreateDataAdapter())
                    {
                        adapter.SelectCommand = command;
                        DataTable dt = new DataTable();
                        adapter.Fill(dt);
                        return dt;
                    }
                }
            }
        }
        catch (Exception)
        {
            throw;
        }
    }
}

好吧,您可以创建一个辅助方法来为您准备命令,或者至少填充参数,例如。

void PrepareParameters(SqlCommand cmd)
{
  cmd.Parameters.AddWithValue("materialName",MaterialName);
  cmd.Parameters.AddWithValue("unitPrice", Price);
  cmd.Parameters.AddWithValue("carbohydrate", Carbohydrtate);
  cmd.Parameters.AddWithValue("protein", Proterin);
  cmd.Parameters.AddWithValue("fat", Fat);
  cmd.Parameters.AddWithValue("humidity", Humadity);
  cmd.Parameters.AddWithValue("minerlas", Minerlas);
}

理想情况下,除非你想使用像实体框架这样的现成的ORM(通常是一个好主意),否则你会创建一些抽象类来处理这些事情,这样你就可以节省代码重用。

例如,PrepareParameters 方法可以是抽象的,并且可能有一个抽象属性返回要更新、创建或删除的 SP 的名称(或者更好的是,您可以遵循命名方案,以便只需要一个名称)。然后你可以在抽象基类中编写 99% 的逻辑,并且只在实际的派生类中准备参数,从而大大减少代码重复。

一些选项如下:

  1. 编写一个 SqlHelper 类,该类执行执行存储过程的重复繁重工作。(尤其是 ExecuteNonQuery 的,这样你就不用担心返回类型了。

例如

public void ExecuteQuery(string sprocName, SqlParamater[] parameters)
{
 // initialize connection
 // construct command with sprocName and parameters
 // ExecuteNonQuery
}
  1. 使用 Linq2Sql

这是一个出色的快速ORM工具,可以简化大量数据访问。

  1. 使用实体框架

这是一个越来越多地使用的ORM工具。

上述所有方法都有其优点/缺点。您需要对它们进行称重并选择正确的方法。