gpt4 book ai didi

NHibernate 更改审计和组件

转载 作者:行者123 更新时间:2023-12-02 01:52:49 28 4
gpt4 key购买 nike

我们架构的一个组成部分,因为我们的系统必须为用户提供一个仪表板,以明确地将数据更改从一个环境发布到另一个环境。我们研究了 NH Evers,但我们需要将许多领域特定的东西融入架构中。我们已经成功地使用 NHibernate 的事件模型来跟踪和记录系统中的状态更改(到另一个表),但最近偶然发现了组件的问题。当 IPostInsertEventListener 和 IPostUpdateEventListener 被触发时,它发布一个值数组,表示实体的当前状态。在更新的情况下,它也会发布一个表示先前状态的数组。我们正在使用这些数组将“之前”和“之后”状态保存到我们的表中。当属性是组件时,实际值(区域中的项目)是组件实例本身 - 即无类型的复杂对象。如果没有交叉引用元模型映射器并对其进行反射(reflection)以提取单个值,我如何才能获得构成组件的实际值?我能够获取映射到组件成员的列名称,但不能获取前后值。

我一直在挖掘 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));
}
}
}

最佳答案

好的,在阅读 NH 代码几个小时后,我偶然发现了 Tuplizers 并将它们追溯到属性 Type。所以解决方案非常简单 - 对于组件,您需要检测它们,转换为 ComponentType 类型,然后向 ComponentType 询问属性值。这里有一些对我有用的代码:

        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, propertyType, report);
}
}
}

report.FinalizeState();

return report;
}

private static void AddColumnChangeReport(AbstractEntityPersister persister, object[] state, object[] oldState, int index, string propertyName, IType propertyType, RowChangedReport report)
{
var currentValue = state[index];

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();

if (propertyType.IsComponentType)
{
ComponentType component = (ComponentType)propertyType;

object[] componentCurrentValues = null;

if (currentValue != null)
componentCurrentValues = component.GetPropertyValues(currentValue, EntityMode.Poco);

object[] componentPreviousValues = null;

if (currentValue != null)
componentPreviousValues = component.GetPropertyValues(previousValue, EntityMode.Poco);

if ((componentCurrentValues != null && componentCurrentValues.Length != columns.Length) ||
(componentPreviousValues != null && componentPreviousValues.Length != columns.Length))
throw new ConventionViolationException(GetComponentArraysExceptionMessage(persister, propertyName, columns, componentPreviousValues, componentCurrentValues));

for (int i = 0; i < columns.Length; i++)
{
var column = columns[i];
var componentPreviousValue = componentPreviousValues == null ? null : componentPreviousValues[i];
var componentCurrnetValue = componentCurrentValues == null ? null : componentCurrentValues[i];

report.AddChange(new ColumnChangedReport(report, propertyName, column, componentPreviousValue, componentCurrnetValue));
}
}
else
{
if (columns.Length > 1)
throw new ConventionViolationException("Expected only component properties to have multiple columns. Property '{0}' on entity {1} is violating that assumption.".FormatWith(propertyName, persister.EntityName));

report.AddChange(new ColumnChangedReport(report, propertyName, columns[0], previousValue, currentValue));
}
}
}

关于NHibernate 更改审计和组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21785194/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com