如何跨两个SQL Server表检索审计跟踪并按正确的顺序将它们放回?

背景背景: 我有一个名为Project的数据库表和一个名为ProjectHistory的表,具有相同的模式。我正在使用nhibernate所以我还有一个名为Project的域对象和一个名为ProjectHistory的域对象(源自Project)。 目标 我的目标是检索这些表中的数据并按照发生的事件将它们按顺序放回,并让C#代码输出最后n次更改的典型审计跟踪屏幕 细节 两个表都具有以下字段和数据类型 Id - (int) - Project中的主键,注意:历史表中没有PK LastUpdated(日期时间) 名称(varchar) 描述(varchar) 时间戳(时间戳) Projecthistory表的目标是每当我对Project表进行更新时,ProjectHistory表都会插入一个带有旧记录的新行,这样我就可以拥有完整的审计跟踪。 我通过使用此触发器实现此目的:
 ALTER TRIGGER ProjectTrigger
 ON Project
 AFTER UPDATE
 AS
    SET NOCOUNT ON

    insert into ProjectHistory
    select * from deleted
我的问题是,我现在需要一些C#代码来汇总审计历史记录,其中用户选择最近n个事件。 例: 以下是事件的示例: 1月10日 - 创建项目1(历史上还没有) 1月11日 - 创建项目2 在1月15日 - 编辑项目2(将项目2的历史表中的条目与1月11日的日期更新为) 1月25日 - 编辑项目1(将项目1的历史表中的条目放在1月10日的日期) 所以,正如你可以看到我是否按历史表中的lastupdated字段降序排序,它将事件4的结果放在事件3的结果之前,这是乱序的。 码 我尝试了以下代码尝试将它们放在一起,但我将解释下面的缺陷:
   public IEnumerable<Project> GetHistory<Project, ProjectHistory>(int numberOfChanges)
    {
        IEnumerable<Project> current;
        IEnumerable<Project> history;
            current = Session.Query<Project>()
                .OrderByDescending(r => r.LastUpdated)
                .Take(numberOfChanges);

             history = Session.Query<ProjectHistory>()
            .OrderByDescending(r => r.LastUpdated).Cast<Project>();

            IEnumerable<Project> all = current.Concat(history);
            return all.OrderByDescending(r => r.Id).ThenByDescending(r => r.LastUpdated);
        }
    } 
我上面代码的主要问题是: 历史记录上的LastUpdated时间将反映上一个Project更新的LastUpdated时间,因此我无法对历史表中该字段的desc进行排序,并假设我将获得正确的事件降序。 我可以使用timestamp字段进行排序(因为这是输入记录的实际时间),但似乎你不能使用C#nhibernate对该字段进行排序,因为该字段只是一个二进制(8)所以它翻译到C#中的byte [],它不支持IComparable。 我可以在Project表上使用lastUpdated字段,因为按lastupdate字段排序将按顺序获取最新的最新事件。我想到只循环项目表,然后为每个项目执行单独的查询以获取最新的历史项目,但是这不支持对同一项目ID进行多次更改的情况。问题是我无法找到以正确顺序获取数据的方法。 我的主要观点是,我想完成我认为必须要解决的非常通用的事情,所以我必须在这里错过基本模式。 我已经有了可以将一个Project对象与另一个项目对象进行比较并返回字段差异的代码(这完美无缺)但我只需要一个建议来确定如何以正确的顺序从这些表中的数据库中获取这些数据(从我的查询或事后的代码)所以我可以显示“最后n个更改”,然后使用我的逻辑显示每个更改的字段差异。     
已邀请:
这是我对一个类似项目的解决方案。创建联合项目和项目历史记录表的视图。让SQL服务器做繁重的工作。 这是一个例子:
CREATE view [dbo].[VwProjectHistory] as select
    OtherFieldName,
    LastUpdated
from
    [dbo].[Project]

union all

select
    OtherFieldName,
    LastUpdated
from
    [dbo].[ProjectHistory]
    
如果我已正确理解您的问题,您只需将时间戳转换为long即可。
// The last row in your question, 0 means start from the start of byte[]
return all.OrderByDescending(r => BitConverter.ToInt64(r.Timestamp,0));
    
选项1: 这是一个允许您在order by子句中使用时间戳的链接。我自己没有使用过,所以请自担风险。 选项2: 向ProjectHistory添加一个自动增量字段,然后您可以按项目的ID和自动增量ID对结果进行排序。我没有太多使用强制转换操作,所以我不确定这些含义,但我相信你会有更多的映射工作。 选项3: 你有没有调查过NHibernate Envers,它是一个支持和审计跟踪的框架?这将是一个新的学习曲线,但从长远来看,它可以为您节省大量的工作。     

要回复问题请先登录注册