【问题标题】:Disabling Database Writes for a Dry Run为试运行禁用数据库写入
【发布时间】:2014-06-19 21:54:00
【问题描述】:

我有一个继承自 MarshalByRefObject 的 Windows 服务。

在运行时,此服务偶尔会收到一个文件:

  • 从数据库中读取数据
  • 进行计算
  • 将结果写入数据库

我想实现一个函数,我们称之为TestRun(),可以远程调用它:

  • 从数据库中读取数据
  • 进行计算
  • 将结果返回给调用者不向数据库写入任何内容

出于显而易见的原因,我希望 TestRun() 使用与常规服务相同的计算代码,其中充斥着 UpdateDatabase() 调用。

这是我目前拥有的简化版本:

static bool commitChanges = true;

public CalcResult TestRun()
{
    try
    {
        commitChanges = false;
        return ProcessData();
    }
    finally
    {
        commitChanges = true;
    }
}

private CalcResult ProcessData()
{
    DataModel data = QueryData();

    //Note: DoCalculations() calls a bunch of other functions with complex
    //      objects many of which make multiple calls to UpdateDatabase().
    CalcResult result = DoCalculations(dataModel);

    return result;
}

private void UpdateDatabase(CalcResult result)
{
    if(commitChanges)
    {
        //Write data to database
    }
}

问题是我很确定如果有人在服务已经在处理数据时调用TestRun(),那么一些真实数据可能不会写入数据库。

有什么比使用布尔标志更好的方法来禁用测试运行的查询?

【问题讨论】:

  • Remoting 是一项遗留技术,保留它是为了与现有应用程序向后兼容,不建议用于新开发。现在应该使用 WCF 或 ASP.NET Web API 开发分布式应用程序。请参阅msdn.microsoft.com/en-us/library/vstudio/xws7132e.aspx 顶部的注释以获取证据。
  • 这不是线程安全的......
  • @AK_ 你读过这个问题了吗?这就是重点。
  • 这在两种情况下非常相关:1) 如果您认为 Remoting 是当前技术,2) 如果未来的读者认为 Remoting 是当前技术。
  • @JohnSaunders 很抱歉我的评论,但似乎是我读得太快了。当我阅读“WCF”时,我在想“WPF”,太多类似的首字母缩略词。也就是说,我完全了解 Microsoft 对 WCF 而不是 Remoting 的建议,但我不知道这将如何解决这里讨论的问题。

标签: c# multithreading remoting


【解决方案1】:

您可以向ProcessData 添加一个可选参数。

public CalcResult TestRun()
{
    return ProcessData(writeToDatabase: false);
}

private CalcResult ProcessData(bool writeToDatabase = true)
{
    DataModel data = QueryData();

    CalcResult result = DoCalculations(dataModel);

    if (writeToDatabase) UpdateDatabase(result);

    return result;
}

private void UpdateDatabase(CalcResult result)
{
    //Write data to database
}

【讨论】:

  • 所提供的例子过于简单了。也许过于简单了。实际上,有数十或数百个 UpdateDatabase() 调用深埋在 DoCalculations() 层次结构中。将一个变量传递给 50 多个函数会使参数列表变得丑陋。我需要一个更中心化的方法,它也是线程安全的。
  • 在 OP 中编辑了示例,希望能更好地说明这一事实。
【解决方案2】:

我找到了一个使用ThreadLocal的解决方案。

我使用 .NET 远程处理编写了一个简单的客户端/服务器测试应用程序,以验证远程处理调用是在新线程上执行的,并且使用 ThreadLocal 可以按预期工作;他们是,而且确实如此。

我换了:

static bool commitChanges = true;

private static ThreadLocal<bool> _commitChanges = new ThreadLocal<bool>(() => true);
private static bool commitChanges
{
    get { return _commitChanges.Value; }
    set { _commitChanges.Value = value; }
}

【讨论】:

  • 注意:通常我会将字段名称大写,但我希望保持与原始示例的命名一致。
猜你喜欢
  • 2018-05-23
  • 1970-01-01
  • 1970-01-01
  • 2021-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-13
  • 1970-01-01
相关资源
最近更新 更多