背景背景:
我有一个名为Project的数据库表和一个名为ProjectHistory的表,其架构相同。我正在使用 nhibernate,所以我还有一个名为Project的域对象和一个名为ProjectHistory的域对象(从Project派生)。
目标
我的目标是跨这些表检索数据,并将它们按发生的事件顺序放回原处,并让 C# 代码输出最后 n 次更改的典型审计跟踪屏幕
细节
两个表都有以下字段和数据类型
- Id -(int)- Project 中的主键,注意:历史表中没有 PK
- 上次更新(日期时间)
- 名称(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 时间将反映上一个项目更新的LastUpdated时间,因此我无法对历史表中的该字段进行降序排序,并假设我将获得正确的事件降序。
- 我可以使用时间戳字段进行排序(因为那是输入记录的实际时间),但您似乎不能使用 C# nhibernate 对该字段进行排序,因为该字段只是一个二进制(8)所以它翻译到 C# 中不支持 IComparable 的 byte[]。
我可以在 Project 表上使用lastUpdated字段,因为按lastupdate字段排序可以让我按顺序获得最近发生的事件。我想过只遍历项目表,然后对每个项目进行单独的查询以获取最新的历史项目,但这不支持对同一项目 ID 进行多次更改的情况。问题是我无法找到以正确顺序获取数据的方法。
我的主要观点是,我想完成我认为必须解决的非常通用的事情,所以我一定只是错过了这里的基本模式。
我已经有代码可以将一个项目对象与另一个项目对象进行比较并返回字段差异(效果很好),但我只需要一个建议来弄清楚我如何以正确的顺序跨这些表从数据库中获取这些数据(无论是从我的查询还是事后的代码中),所以我可以显示“最后 n 次更改”,然后使用我的逻辑来显示每个更改的字段差异。