C# NHibernate,将数据库中的空参考值保存为0(零)

C# NHibernate,将数据库中的空参考值保存为0(零),c#,nhibernate,legacy-database,tuplizer,C#,Nhibernate,Legacy Database,Tuplizer,我发现这个tuplizer示例在保存空关系时执行save 0。这是必需的,因为我正在使用遗留数据库模式开发应用程序 我在这里试用了tuplizer: 在那个例子中,我得到了ProxyFactory的nullreferenceexception。然后我在这里找到了代码的更新: 然而,这对我也不起作用。在最后一个方法SetPropertyValues(描述为DirtyHack 3,在从DB读取对象时使用)中,当读取一个不相关的对象(不是示例)时,我在这一部分得到了一个nullref异常if(type

我发现这个tuplizer示例在保存空关系时执行save 0。这是必需的,因为我正在使用遗留数据库模式开发应用程序

我在这里试用了tuplizer:

在那个例子中,我得到了ProxyFactory的nullreferenceexception。然后我在这里找到了代码的更新:

然而,这对我也不起作用。在最后一个方法SetPropertyValues(描述为DirtyHack 3,在从DB读取对象时使用)中,当读取一个不相关的对象(不是示例)时,我在这一部分得到了一个nullref异常if(typeof(ienty))

我的映射如下(简化):


如何实现这一点?简单的解决方案是添加以下preinsert和preupdate侦听器

public class NullToZeroEventListener : AuditEventListener, IPreInsertEventListener, IPreUpdateEventListener
{
    public bool OnPreInsert(PreInsertEvent @event) {
        ZeroNullIds(@event.State, @event.Persister.PropertyNames);
        return false;
    }

    public bool OnPreUpdate(PreUpdateEvent @event) {
        ZeroNullIds(@event.State, @event.Persister.PropertyNames);
        return false;
    }

    protected internal void ZeroNullIds(Object[] state, string[] propertyNames) {
        for(int i = 0; i < propertyNames.Length; i++) {
            if(state[i] != null || propertyNames[i].EndsWith("ID")) continue;
            state[i] = 0;
        }
    }
}

简单的解决方案是添加以下预插入和预更新侦听器

public class NullToZeroEventListener : AuditEventListener, IPreInsertEventListener, IPreUpdateEventListener
{
    public bool OnPreInsert(PreInsertEvent @event) {
        ZeroNullIds(@event.State, @event.Persister.PropertyNames);
        return false;
    }

    public bool OnPreUpdate(PreUpdateEvent @event) {
        ZeroNullIds(@event.State, @event.Persister.PropertyNames);
        return false;
    }

    protected internal void ZeroNullIds(Object[] state, string[] propertyNames) {
        for(int i = 0; i < propertyNames.Length; i++) {
            if(state[i] != null || propertyNames[i].EndsWith("ID")) continue;
            state[i] = 0;
        }
    }
}

您将非相关的
ISession
转换为
ISessionImplementor
。更安全的是
会话。GetSessionImplementor()
您将非相关的
ISession
转换为
ISessionImplementor
。更安全的是
会话。GetSessionImplementor()
提示:“Pre”事件侦听器的正式用途不是修改实体。请改用DefaultSaveEventListener。我知道Internet上充满了修改实体的“Pre”侦听器示例,但Hibernate开发人员回答说不支持这种用法,因此可能会产生新问题。提示:“Pre”事件监听器的正式用途不是修改实体。请改用DefaultSaveEventListener。我知道Internet上充满了修改实体的“Pre”监听器示例,但Hibernate开发人员回答说不支持这种用法,因此可能会产生新的问题。
        public override object[] GetPropertyValuesToInsert(object entity, IDictionary mergeMap, ISessionImplementor session) {
        var values = base.GetPropertyValuesToInsert(entity, mergeMap, session);

        //dirty hack 1
        for(int i = 0; i < values.Length; i++) {
            if(values[i] == null && typeof(IEntity).IsAssignableFrom(getters[i].ReturnType)) {
                //values[i] = ((ISession)session).Load(getters[i].ReturnType, 0);
                values[i] = CreateFakeProxy(i);
            }
        }
        return values;
    }

    private object CreateFakeProxy(int i) {
        object proxy;
        using(var sessionImplementor = _sessionFactory.OpenSession()) {
            proxy = _sessionFactory
                .GetEntityPersister(getters[i].ReturnType.FullName)
                .CreateProxy(0, (ISessionImplementor)sessionImplementor);
        }
        return proxy;
    }
        private readonly ISessionFactoryImplementor _sessionFactory;

    public NullableTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity)
        : base(entityMetamodel, mappedEntity) {
            _sessionFactory = entityMetamodel.SessionFactory;

    }
public class NullToZeroEventListener : AuditEventListener, IPreInsertEventListener, IPreUpdateEventListener
{
    public bool OnPreInsert(PreInsertEvent @event) {
        ZeroNullIds(@event.State, @event.Persister.PropertyNames);
        return false;
    }

    public bool OnPreUpdate(PreUpdateEvent @event) {
        ZeroNullIds(@event.State, @event.Persister.PropertyNames);
        return false;
    }

    protected internal void ZeroNullIds(Object[] state, string[] propertyNames) {
        for(int i = 0; i < propertyNames.Length; i++) {
            if(state[i] != null || propertyNames[i].EndsWith("ID")) continue;
            state[i] = 0;
        }
    }
}
           .ExposeConfiguration(c =>
            {
                if(!c.EventListeners.PreInsertEventListeners.Any()) {
                    c.AppendListeners(ListenerType.PreInsert, new IPreInsertEventListener[] { new NullToZeroEventListener() });
                }
            });