【问题标题】:writing more optimized code and reusing code in C#在 C# 中编写更优化的代码和重用代码
【发布时间】:2014-03-31 06:45:16
【问题描述】:

我正在使用 C# winforms 和 MSSQL server 2012 编写桌面应用程序。此应用程序中有几个类需要连接到数据库和所有 uisng 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() 中看到的那样,我使用相同的代码连接到数据库并调用存储过程,这在我的其他类中重复了多次。我怎样才能防止这个代码重复?有没有办法只编写连接所需的代码并查询一次数据库并根据需要多次重用它?

【问题讨论】:

  • 您应该研究诸如企业库甚至实体框架之类的包装器。
  • 创建一个处理所有数据库操作的 database_class。

标签: c# sql .net oop design-patterns


【解决方案1】:

我为我的数据库连接使用工厂模式,这意味着我永远不必打开 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;
        }
    }
}

【讨论】:

  • ,一段漂亮的代码!你在哪里学会写这样的代码?在大学里从来没有人这样教过我们吗?
  • @Latrochemist 我建议阅读Head First Design Patterns
【解决方案2】:

好吧,你可以制作一个辅助方法来为你准备命令,或者至少填写参数,例如。

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 的名称(或者更好的是,您可以遵循命名方案以便您d 只需要一个名字)。然后你可以在抽象基类中编写 99% 的逻辑,而只在实际派生类中准备参数,从而减少代码重复 很多

【讨论】:

  • 即使是 EF。我使用 EF,但在我自己的代码中执行所有 sp 调用。 EF 很简单——不处理参数,你调用一个类型的方法(返回类)并放入参数,其余的都是自动完成的。你可以把它减少到一个衬里。
【解决方案3】:

一些选项如下:

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

例如

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

这是一款出色的快速 ORM 工具,可极大地简化数据访问。

  1. 使用实体框架

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

上述所有方法都有其优点/缺点。您需要权衡它们并选择正确的方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-01
    • 2012-06-08
    • 2015-04-26
    • 1970-01-01
    • 2012-11-13
    • 1970-01-01
    • 2013-01-17
    • 1970-01-01
    相关资源
    最近更新 更多