【问题标题】:Which design pattern for Activity Logging (Audit Trailing)活动记录(审计跟踪)的设计模式
【发布时间】:2012-06-18 08:55:48
【问题描述】:

我有一个允许人们编辑数据库中的数据的 winform,为了简化操作,假设数据库中有一个 Customer 表,其中包含 3 个字段 - 名称、城市、国家。通过 winform,人们可以添加/编辑/删除客户。

对于我们需要保存的每个操作:

  1. 字段名称是什么(在本例中为名称、城市、国家/地区)

  2. 字段值在修改之前是什么

  3. 修改后的字段值是什么。

如果操作是添加或删除,那么 2 和 3 将是相同的。

我已经使用 XMLSerialisation 实现了这个(但没有使用任何设计模式),我的 XML 输出看起来像这样。

<?xml version="1.0" encoding="utf-8"?>
<ActivityItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <UserID>26</UserID>
  <FormTitle>frmCustomer</FormTitle>
  <Action>Edit</Action>
  <Area>Customers</Area>
  <TrackedActivity>
    <FieldNames>
      <string>Name</string>
      <string>City</string>
      <string>Country</string>
    </FieldNames>
    <PreValues>
      <string>CompA</string>
      <string>London</string>
      <string>UK</string>
    </PreValues>
    <PostValues>
      <string>CompB</string>
      <string>Manchester</string>
      <string>UK</string>
    </PostValues>
  </TrackedActivity>
  <DateTimeStamp>2012-06-15T10:16:18</DateTimeStamp>
</ActivityItem>

该解决方案可以使用不同数量的字段处理系统的不同区域(例如,当您修改产品时,同样的事情会起作用)。

我的问题是,是否有定义明确的设计模式来处理这种行为?

非常感谢

【问题讨论】:

    标签: c# vb.net oop design-patterns xml-serialization


    【解决方案1】:

    我会做什么......制作几个课程。有一个“审计日志”的东西收集了一堆“审计记录”的东西。每条审计记录都是EditDelete,并包含已更改的记录和对象的旧值(如果适用)。

    好的,因为将涉及多个对象类型(客户、产品...),这对我来说意味着这些类型应该是通用的。

    这让我想到:

    public class AuditLog<T>
    {
        public int UserID   { get; set; }
        public string LastSaved   { get; set;}
    
        [XmlArrayItem("Entry")]
        public List<AuditRecord<T>> Records;
    }
    
    public enum Flavor
    {
        Edit,
        Delete
    }
    
    public class AuditRecord<T>
    {
        public AuditRecord() { Stamp = DateTime.Now; }
    
        [XmlAttribute("action")]
        public Flavor Action  { get; set;}
    
        [XmlAttribute("stamp")]
        public DateTime Stamp   { get; set;}
    
        public T Before;
        public T After; // maybe null
    }
    

    然后对于这样的课程

    public class Customer
    {
        public string Name   { get; set; }
        public string City   { get; set; }
        public String Country   { get; set; }
    }
    

    ...你会得到这样的文件:

    <AuditLogOfCustomer>
      <UserID>0</UserID>
      <LastSaved>2012 Jun 16 20:42:53</LastSaved>
      <Records>
        <Entry action="Edit" stamp="2012-06-16T20:42:52.9622344-07:00">
          <Before>
            <Name>Sheldon</Name>
            <City>Ipswich</City>
            <Country>UK</Country>
          </Before>
          <After>
            <Name>Sheldon</Name>
            <City>London</City>
            <Country>UK</Country>
          </After>
        </Entry>
        <Entry action="Delete" stamp="2012-06-16T20:42:52.9642345-07:00">
          <Before>
            <Name>Sheldon</Name>
            <City>London</City>
            <Country>UK</Country>
          </Before>
        </Entry>
      </Records>
    </AuditLogOfCustomer>
    

    代码: http://pastebin.com/PKiEefnX

    【讨论】:

    • 谢谢你,但我已经得到了类似的代码,我正在寻找的是尝试利用其中一种设计模式(可能会也可能不会)..
    【解决方案2】:

    我还没有听说过一个特定的设计模式可以做到你在这里描述的那样,但我会称之为离线可更新数据库快照

    如果我正确阅读了您的描述,您将描述 dotnet dataset 自 dotnet 1.0 以来所做的事情,并且仍在使用 vs2010/dotnet 4.0,但不再由微软推广。

    • 您有每个对象类型的数据表(在您的示例客户中)
    • 您有包含字段(名称、城市、国家/地区)的数据行
    • 有不同的行版本(原始的,实际的)
    • 您可以(反)将其序列化为 xml(WriteXml、LoadXml、GetXml)

    您的描述中缺少的是一个rowstate,可用于指示已删除的行。

    【讨论】:

    • 感谢您的输入,您可能是对的,可能没有特定的设计模式可以满足我的要求。
    猜你喜欢
    • 2013-10-25
    • 2011-11-26
    • 1970-01-01
    • 1970-01-01
    • 2018-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-23
    相关资源
    最近更新 更多