Frage

Ich habe dieses Beispiel eines Tuplizers gefunden, der beim Speichern von Nullbeziehungen „0“ speichert.Dies ist erforderlich, da ich an einer App mit einem alten Datenbankschema arbeite.

Ich habe den Tuplizer hier ausprobiert: http://nhforge.org/blogs/nhibernate/archive/2011/01/28/how-to-use-0-instead-of-null-for-foreign-keys.aspx

In diesem Beispiel habe ich eine NullreferenceException für die ProxyFactory erhalten.Dann habe ich hier ein Update zum Code gefunden: https://bitbucket.org/jfromaniello/hotgazpachoeg/changeset/87ac41c473ae

Allerdings funktioniert das bei mir auch nicht.In der letzten Methode, SetPropertyValues ​​(beschrieben als Dirty Hack 3, wird beim Lesen eines Objekts aus der Datenbank verwendet), erhalte ich eine Nullref-Ausnahme für diesen Teil, if(typeof(IEntity), wenn ich ein nicht verwandtes Objekt (kein Beispiel) lese.

Meine Zuordnung ist wie folgt (vereinfacht):

   Table("ej_sample");
        Not.LazyLoad();
        Id(s => s.Id, "sampleID").GeneratedBy.Native();
        References<Sample>(s => s.ParentSample, "parentSampleID").NotFound.Ignore();

Die Spalte „parentSampleID“ muss 0 sein, wenn kein solches Objekt vorhanden ist.

Ich dachte, ich muss nur die schmutzigen Hacks beim Einfügen und Aktualisieren durchführen (in meinem Fall möglicherweise nur beim Einfügen).

Beim Einfügen möchte ich einen gefälschten Proxy erstellen, aber der Code in [2] lädt die Entität aus der Datenbank (möglicherweise um ein Null-Objekt zu verwenden?!).

Dirty Hack einfügen:

        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);
            }
        }
        return values;
    }

Ich habe versucht, einen gefälschten Proxy zu erstellen, anstatt wie oben beschrieben vorzugehen:

        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;
    }

Dann erhalte ich eine Nullref-Ausnahme für die _sessionfactory, die im Ctor festgelegt ist:

        private readonly ISessionFactoryImplementor _sessionFactory;

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

    }

Irgendwelche Ideen, wie man das erreichen kann?

War es hilfreich?

Lösung

Die einfache Lösung besteht darin, den folgenden PreInsert- und PreUpdate-Listener hinzuzufügen.

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;
        }
    }
}

Achten Sie bei der Zuordnung darauf, 0 IDs zu ignorieren, zum Beispiel:References<User>(s => s.User, "userID").NotFound.Ignore().LazyLoad();

Fügen Sie in Ihrer Sessionfactory einen Listener für Preinsert- und Preupdate-Ereignisse hinzu (zuerst hier gezeigt):

           .ExposeConfiguration(c =>
            {
                if(!c.EventListeners.PreInsertEventListeners.Any()) {
                    c.AppendListeners(ListenerType.PreInsert, new IPreInsertEventListener[] { new NullToZeroEventListener() });
                }
            });
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top