【问题标题】:Global objects vs multiple new objects?全局对象与多个新对象?
【发布时间】:2011-09-20 10:17:13
【问题描述】:

假设我有一个方法,该方法需要在每次运行期间创建少量对象,并且该方法将被多次调用,即从数据库中删除给定行的方法。每次都创建一个新对象并调用垃圾收集器(或类似的)在最后销毁它,还是每次都重新初始化该值会更好吗?

示例:
每次都使用新的构造函数:

private void RemoveFolder(string dir)
{
    OleDbCommand cmd2 = connection.CreateCommand();
    OleDbParameter parameterC = new OleDbParameter();
    cmd2.Parameters.Add(parameterC);
    parameterC.Value = dir;

    cmd2.CommandText = "DELETE * FROM [Directories] WHERE Path = ?";
    cmd2.ExecuteNonQuery();
    cmd2.Dispose();
}

使用单个全局变量(在构造函数中初始化):

private void RemoveFolder(string dir)
{
    parameterC.Value = dir;

    cmd2.CommandText = "DELETE * FROM [Directories] WHERE Path = ?";
    cmd2.ExecuteNonQuery();
}

编辑:当我说得更好时,我的意思是在正常的非“关键任务”程序中“作为一个整体”,其中性能的大幅提升将胜过稳定性的小幅下降.

EDIT2

多次调用类似方法的示例

(注意这是我的另一种方法,AddFolder)

foreach (DirectoryInfo directory in directories)
{
    parameter.Value = directory.FullName;
    cmd.CommandText = "SELECT LastModified FROM Directories WHERE Path = ?";
    reader = cmd.ExecuteReader();

    while (reader.Read())
    {
        output += reader.GetString(0);
    }

    if (output == null)
    {
        Console.WriteLine("New Directory! " + directory.FullName);
        AddFolder(directory);
    }
    output = null;
    reader.Close();
 }

【问题讨论】:

  • 能否请您显示多次执行此方法的代码

标签: c# ms-access object oledb methodology


【解决方案1】:

您的问题是我需要优化该代码吗?

我的总体看法,

  1. 如果两个容易优化它,并且代码仍然比它简单, 否则,如果不确定它是否会产生影响而不是这样,
  2. 如果不确定,请测量它
  3. 在相关代码附近留下评论

如何测量它? 您可以查看您的程序是否运行缓慢,或者它是否使用了太多内存..

【讨论】:

    【解决方案2】:

    关于您的第二次编辑,

    您可以将 foreach 循环转换为 LINQ, 聚合所有目录,然后立即 将目录添加到您的数据库中

    你的代码会看起来更优雅,它会解决你的主要问题

    http://www.linqtutorial.net/linqExamples.html有一段如何用LINQ替换迭代循环

    【讨论】:

      【解决方案3】:

      您在这里遇到的主要性能问题是您为查询的“准备”支付了多少费用。准备是解析查询和(更重要的是)确定查询计划的地方。查询计划的确定可能相当昂贵,您希望尽量减少必须完成的次数

      (注意:即使您示例中的 DELETE ... WHERE ... 也需要查询计划。)

      某些 DBMS 和 ADO.NET 提供程序在“重用”查询计划方面比其他提供程序更好。例如,在 Oracle/ODP.NET 上,您是否反复重新创建 DbCommand 可能并不重要 - Oracle 将倾向于“看到”这是以前使用的相同查询并重用查询计划。

      另一方面,如果您想确保查询准备一次并重复使用多次,无论您使用什么 DBMS,保持相同的 DbCommand 对象不是一个坏主意在整个应用程序执行过程中(甚至显式调用 DbCommand.Prepare),如下所示:

      var conn = new OracleConnection("your connection string"); // Or DB2Connection, SqlConnection or NpgsqlConnection or whatever...
      conn.Open();
      
      // Execute once:
      var cmd = conn.CreateCommand();
      cmd.CommandText = "DELETE FROM YOUR_TABLE WHERE YOUR_FIELD = :your_param";
      var param = cmd.CreateParameter();
      param.ParameterName = "your_param";
      param.DbType = ...;
      cmd.Parameters.Add(param);
      cmd.Prepare(); // Not really important for Oracle, but may be important for others.
      
      // Execute multiple times:
      param.Value = "some value";
      int row_count = cmd.ExecuteNonQuery();
      
      // If you are concerned with long-lived connections, you'll typically be able to do this:
      conn.Close();
      // ...
      conn.Open();
      param.Value = "some other value";
      row_count = cmd.ExecuteNonQuery();
      
      // Etc..
      

      所以:

      • 如果您的程序仅在单个 DBMS/ADO.NET 提供程序上运行,并且您知道它将有效地重用查询计划,并且您不介意稍微昂贵的 C# 代码,那么您可能会选择“重复重新创建”解决方案。它还可能允许稍微短一点的 C# 代码。
      • 但是,我更喜欢“创建一次,多次重复使用”的解决方案 - 无论我使用什么 DBMS,我都会获得最佳性能。即使在那些智能到足以重用查询计划的 DBMS 下,我仍然会避免重新执行 C# 代码和相关的垃圾收集压力。

      【讨论】:

        【解决方案4】:

        我认为这里的关键建议是不要留下挥之不去的数据库连接,然后在临时基础上打开和操作。我注意到您的问题实际上围绕是否重用命令 - 当,在查看时,注意到您的连接必须已经是可重用的......我不建议这样做,并建议您将每个数据库操作视为一个原子单元工作量,包括连接利用率等。

        【讨论】:

        • 我通常会完全同意你的看法。但是,在扫描更改后连接会关闭(当前为 10 秒)。每次编辑都重新打开连接太慢而无法使用
        【解决方案5】:

        最好使用第一种方法,这样执行查询的逻辑就停留在单个函数中。

        【讨论】:

          【解决方案6】:

          我认为正确的版本介于两者之间

          public foo() 
          {
             var context = generateContext(dir);
             context.excute();
          }
          

          把两个目标分开

          1. 创建上下文
          2. 执行它

          在创建上下文中使用可以使用单例

          【讨论】:

            【解决方案7】:

            我更喜欢使用全局变量,而不是每次操作都重新创建相同的对象。 一次性分配成本很小,而每次迭代创建对象的成本可能很高。

            【讨论】:

            • 这是我的想法。然而,我有幸见到的每个开发人员都表示,全局变量(或对象)一般来说是个坏消息。因此我的困境......
            猜你喜欢
            • 1970-01-01
            • 2021-12-30
            • 1970-01-01
            • 2016-02-16
            • 1970-01-01
            • 1970-01-01
            • 2021-07-31
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多