2

需要记录一些“高风险”数据操作。在这种情况下,“高风险”操作被定义为写入我们的 ERP 系统。碰巧我们正在将这些事件记录到我们的 SQL Server 数据库中。

伪代码:

Public Class MyCompany.DAL.ERP {
  Public void WriteToERP(string msg) {
    // ... do the write
    MyCompany.Logging.Write("Wrote msg: " + msg);
  }
}

Public Class MyCompany.Logging {
  Public void Write(string msg) {
    MyCompany.DAL.ExecuteSQL("Insert INTO EventLog VALUES " + msg);
  }
}

消除这种紧密耦合的最佳做法是什么?

4

7 回答 7

3

嗯,恕我直言,日志记录是一个基础设施问题。你可以在你的 DAL 中使用它,但你的记录器不应该使用你的 DAL。

如果您删除了您的记录器对 DAL 的依赖,那么您应该也可以在其他项目中使用您的记录器。

于 2009-01-20T19:19:09.187 回答
1

您可以创建自定义 TraceListener (System.Diagnostics) 以插入公司的 SQL Server 数据库。然后使用 Trace / TraceSource (System.Diagnostics) 登录应用程序代码。然后,您可以使用标准 .NET 配置在设计时使用您的自定义 TraceListener。这样,如果您需要更改事件日志记录,您只需更改 TraceListener。另外,您可以在其他应用程序中重用 TraceListener。

您还可以使用企业库的日志记录应用程序块和许多其他第 3 方日志记录解决方案。

于 2009-01-20T19:20:33.520 回答
0

也许您可以将日志记录组件移至单独的程序集(我假设这是 C# 代码),引发一个事件,调用者可以在调用 Logging.Write() 之前注册该事件。在 Logging.Write() 返回后,从事件中注销。在事件处理程序中,您可以执行 MyCompany.DAL.ExecuteSQL("Insert INTO EventLog VALUES " + msg) 调用。

于 2009-01-20T19:18:27.237 回答
0

我之前通过两种方式解耦了这种情况:状态变化和日志事件。

第一种方法是创建一个 IHaveStatus 接口,如下所示:

/// <summary>
/// Interface for objects that have a status message 
/// that describes their current state.
/// </summary>
public interface IHaveStatus
{
    /// <summary>
    /// Occurs when the <seealso cref="Status"/> property has changed.
    /// </summary>
    event EventHandler<StatusChangedEventArgs> StatusChanged;
    /// <summary>
    /// The current status of the object.  When this changes, 
    /// <seealso cref="StatusChanged"/> fires.
    /// </summary>
    string Status { get; }
}

当你的对象做事时,你设置你的 Status 属性。您可以将属性设置器配置为在设置时触发 StatusChanged 事件。使用您的对象的任何人都可以侦听您的状态更改事件并记录发生的所有事情。

另一个版本是向您的对象添加日志事件。

public event EventHandler<LogEventArgs> Log;

主体几乎相同,只是您的对象比状态驱动的日志更健谈(只有在您特别想记录某些内容时才会触发该事件)。

这个想法是 DAL 之外的调用者有责任将这些事件连接到正确的日志(希望通过使用 DI 设置)。您的 DAL 不知道是谁或什么在消耗这些事件,从而很好地区分了这些问题。

于 2009-01-20T19:24:38.580 回答
0

响应之间的共同点似乎是建议实现类似于观察者模式的东西。

(如果有更好的总结性陈述,请告诉我。我会相应地更新。)

于 2009-01-20T19:32:31.560 回答
0

实际上,如果您所说的高风险数据是指关键/重要的是要知道它应该是数据的方式,并且如果您需要在数据库中保存日志(某种元数据),那么解决方案应该与其他人建议的完全不同。

我描述的情况意味着数据库事务的结果在任何给定时间都应该在数据库中同时包含日志记录数据和数据本身。一个不应该独立于另一个来完成。

因此,这种“日志记录”应该作为单个数据库事务的一部分来完成,并且 DAL 应该确保在同一事务中同时正确插入这两个项目。

不这样做可能会产生以下副作用:

  • 只有一个数据或日志插入到数据库中。
  • 只有一个数据或日志在另一个之前插入到数据库中,这意味着依赖于在任何给定时间都必须存在的事实的系统可能会在特定情况下随机失败。
于 2009-01-20T20:46:31.223 回答
0

为了避免循环依赖 DAL -> Logger -> DAL,我建议你有两层 DAL:“simple DAL”和“logging DAL”。

“简单 DAL”只是一个 DAL。“日志记录 DAL”建立在“简单 DAL”之上;它使用简单的 DAL 操作数据库,并再次使用简单的 DAL 记录内容。所以你有了:

[应用程序逻辑] --uses--> [logging DAL] --uses--> [simple DAL] --uses--> DB

如果你想对不需要记录的数据库做一些事情(“低风险”操作;-))你可以直接使用“简单 DAL”并绕过记录 DAL。

于 2009-01-24T02:32:43.410 回答