NHibernate事件侦听器深度克隆对象

本文关键字:对象 深度 事件 侦听器 NHibernate | 更新日期: 2023-09-27 18:27:56

我试图在OnPostUpdate事件中获取更新实体的旧状态。@event参数的OldState属性将对象作为数组返回,我需要它作为对象。我尝试了以下方法:

public class EventListener : IPostUpdateEventListener {
    public void OnPostUpdate(PostUpdateEvent @event) {
        // Get the property names to align with the indexes of the old state
        var propertyNames = @event.Persister.PropertyNames;
        // Get the original entity values
        var type = @event.Entity.GetType();
        var original = Activator.CreateInstance(type);
        // Set the values
    for (var i = 0; i < @event.OldState.Length; i++) {
        // Get the property and value
        var property = type.GetProperty(@event.Persister.PropertyNames[i]);
        var value = @event.OldState[i];
        if (property.CanWrite && !(@event.Persister.PropertyTypes[i] is CollectionType)) {
            if (value != null && (@event.Persister.PropertyTypes[i] is ComponentType || @event.Persister.PropertyTypes[i] is EntityType))
                property.SetValue(original, CloneObject(value));
            else
                property.SetValue(original, value);
        }
    }
}

这是CloneObject方法:

private object CloneObject(object source) {
    var sourceType = source.GetType();
    var target = Activator.CreateInstance(sourceType, true);
    foreach (var property in type.GetProperties()) {
        var value = property.GetValue(source, null);
        if (property.CanWrite && (property.PropertyType == typeof(string) || !typeof(IEnumerable).IsAssignableFrom(property.PropertyType)) && !property.PropertyType.IsInterface) {
            if (value != null && typeof(IEntity).IsAssignableFrom(property.PropertyType))
                property.SetValue(target, CloneObject(value));
            else
                property.SetValue(target, value);
        }
    }
    return target;
}

我做的第一件事是循环原始对象中的属性,然后尝试处理组件和引用类型(忽略列表)。这将正确复制对象。然而,它随后抛出错误:

flush()未处理集合[Models.ContentType.Tags]

编辑:ContentType类是我正在更新的某个属性的类型。以下是它的实现,如果它有帮助:

public class ContentType : Entity<int> {
    public virtual string Name { get; set; }
    public virtual IList<ContentTag> Tags { get; set; }
    public ContentType() {
        Tags = new List<ContentTag>();
    }
}

当我试图获取其他实体的旧状态时,我也会遇到类似的错误。如果有人能告诉我做这件事的正确方法,我将不胜感激。感谢

NHibernate事件侦听器深度克隆对象

编辑

虽然你似乎没有接触任何藏品,但关于这个问题:

在PostUpdateEvent 中迭代集合时,刷新未处理集合

你可以尝试这个答案,以确保它不是你的问题的原因:

https://stackoverflow.com/a/11575172/1236044


了解触发错误的行将非常有帮助。

property.SetValue(target, CloneObject(value));中的CloneObject是什么?

您是否尝试将var value = ...这两行移动到相应的if语句中?这样,只有在真正需要的时候才能处理价值。

    var value = @event.OldState[i];
    if (property.CanWrite && !(@event.Persister.PropertyTypes[i] is CollectionType)) {
        if (value != null && (@event.Persister.PropertyTypes[i] is ComponentType || @event.Persister.PropertyTypes[i] is EntityType))

成为

    if (property.CanWrite && !(@event.Persister.PropertyTypes[i] is CollectionType)) {
        var value = @event.OldState[i];
        if (value != null && (@event.Persister.PropertyTypes[i] is ComponentType || @event.Persister.PropertyTypes[i] is EntityType))

    var value = property.GetValue(source, null);
    if (property.CanWrite && (property.PropertyType == typeof(string) || !typeof(IEnumerable).IsAssignableFrom(property.PropertyType)) && !property.PropertyType.IsInterface) {
        if (value != null && typeof(IEntity).IsAssignableFrom(property.PropertyType))

成为

    if (property.CanWrite && (property.PropertyType == typeof(string) || !typeof(IEnumerable).IsAssignableFrom(property.PropertyType)) && !property.PropertyType.IsInterface) {
        var value = property.GetValue(source, null);
        if (value != null && typeof(IEntity).IsAssignableFrom(property.PropertyType))