我们的系统架构的一个重要组成部分是必须为用户提供仪表板,以便他们能够明确地将数据更改从一个环境发布到另一个环境。我们研究了NH Evers,但我们需要将许多特定于领域的内容融入到架构中。我们一直在成功地使用NHibernate的事件模型来跟踪和记录系统中的状态更改(到另一个表),但最近在组件方面遇到了问题。当IPostInsertEventListener和IPostUpdateEventListener被触发时,它会发布表示实体当前状态的值数组。在更新的情况下,它还会发布表示先前状态的数组。我们正在使用这些数组将“之前”和“之后”的状态保存到我们的表格中。当属性是一个组件时,实际值(区域中的项目)是组件实例本身 - 即一个未打包的复杂对象。除了交叉引用元模型映射器并反射出该映射器以提取各个值之外,我如何获取组件的实际值?我能够访问映射到组件成员的列名,但无法访问之前和之后的值。
我一直在搜索NH源代码,但没有找到如何提取这些值的方法。显然,NH知道如何在内部执行此操作,因为它能够正确地发布SQL。这是我目前拥有的代码的修改/详细版本,突出了问题:
我一直在搜索NH源代码,但没有找到如何提取这些值的方法。显然,NH知道如何在内部执行此操作,因为它能够正确地发布SQL。这是我目前拥有的代码的修改/详细版本,突出了问题:
public static RowChangedReport Load(IChangeTrackable trackable, object entityId, AbstractEntityPersister persister, object[] state, object[] oldState)
{
var report = new RowChangedReport
{
Entity = trackable,
EntityTypeFullName = persister.EntityName,
TableName = new TableName(persister.GetTableName()),
EntityId = entityId,
};
var authContext = AuthenticationContext.Current;
if (authContext != null)
report.SecurityContextUserId = authContext.UserId;
if (persister.PropertyNames != null && state != null)
{
report.ChangedType = oldState == null ? RowChangedTypes.New : RowChangedTypes.Modified;
for (var index = 0; index < persister.PropertyNames.Length; index++)
{
var propertyName = persister.PropertyNames[index];
IType propertyType = persister.PropertyTypes[index];
if (!propertyType.IsCollectionType)
{
AddColumnChangeReport(persister, state, oldState, index, propertyName, report);
}
}
}
report.FinalizeState();
return report;
}
private static void AddColumnChangeReport(AbstractEntityPersister persister, object[] state, object[] oldState, int index, string propertyName, RowChangedReport report)
{
var currentValue = state[index];
// for simple properties, this is always a single element array
// for components, this is an array with an element for each member on the component - i.e. how the component is mapped
string[] columns = persister.GetPropertyColumnNames(propertyName);
var previousValue = oldState == null ? null : oldState[index];
if (!Equals(currentValue, previousValue))
{
if (report.ChangedType == RowChangedTypes.Modified && propertyName == IsActivePropertyName)
report.FlagAsDeleted();
foreach (var column in columns)
{
// if this is a component, both the currentValue and the previousValue are complex objects
// need to have a way to get the actual member value per column!
report.AddChange(new ColumnChangedReport(report, propertyName, column, previousValue, currentValue));
}
}
}