Auswirkungen auf NHibernate Caching für Suchen mit Ergebnissen, einschließlich als Formel kartiert berechneten Wert (z Rang)

StackOverflow https://stackoverflow.com/questions/1627707

Frage

Bei der Definition einer berechneten Eigenschaft eine Formel in NHibernate, was sind die Auswirkungen auf, wenn die Formel ändert sich das Ergebnis auf den Abfrage Einschränkungen abhängig, vor allem im Hinblick Caching abzufragen?

Insbesondere die folgende einfache C # Klasse:

public class Entity
{
    public Entity() { }
    public virtual int Id { get; protected set; }
    public virtual string Key { get; protected set; }
    public virtual string Value { get; protected set; }
    public virtual int Rank { get; protected set; }
}

Mapped mit dem folgenden einfachen NHibernate-Mapping:

<class name="Entity" mutable="false">
    <id name="Id">
        <generator class="native">
    </id>
    <property name="Key"/>
    <property name="Value"/>
    <property name="Rank" formula="row_number() over(order by value)">
</class>

Beim Laufen mit einer Sitzung Fabrik mit hibernate.cache.use_query_cache Option auf true und auf folgende Weise abgefragt:

ICriteria criteria = session.CreateCriteria(typeof(Entity));
criteria.SetCacheable(true);
criteria.SetCacheRegion("SearchResults");
IList<Entity> queryResult1 = criteria.List<Entity>();

criteria = session.CreateCriteria(typeof(Entity));
criteria.SetCacheable(true);
criteria.SetCacheRegion("SearchResults");
criteria.Add(Restrictions.Like("Key", "a", MatchMode.Anywhere));
IList<Entity> queryResult2 = criteria.List<Entity>();

Entity directResult = session.Load<Entity>(id);

Will NHibernate verhalten in angemessener Weise für die zurückgegebenen Entitäten? Oder könnte der „Rank“ Wert aus einer zwischengespeicherten Abfrage den Rang Wert einer anderen Abfrage verschmutzt aufgrund der Abfrage-Cache? Gibt es noch andere Bedenken, wenn eine solche Formel in NHibernate Zuordnungen verwenden?

EDIT:

Es könnte auch wert sein, stellt fest, dass in meinem Fall, „Entity“ ist kein First-Class-Business-Einheit, sondern eine Art von Meta-Einheit. Es bildet auf eine indizierte Datenbank Sicht gegenüber anderen erstklassigen Einrichtungen und dient ausschließlich für die Suche (die session.Load (id) Aufruf ist gekünstelt und sollte nie in der Praxis tatsächlich geschehen).

Und wenn es sind Auswirkungen auf Caching, wie ich vermute, welche Alternativen könnten für einen ähnlichen Anwendungsfall gibt es mögliche Probleme zu vermeiden?

War es hilfreich?

Lösung

Nach weiteren Experimenten: Ja, es gibt Cache Implikationen, die in inkonsistenten Ergebnissen führen könnten; NHibernate kann nicht automatisch wissen, dass die Formel Wert zwischen Abfragen für Unternehmen Ergebnisse mit der gleichen Kennung ändern könnte (und nimmt es nicht).

eine Klasse Zuordnung wie die in der fraglichen in den Rang führen würde, dass mit dem Rest der Einheit Daten gespeichert. Dies macht es möglich, dass eine nachfolgende Abfrage einen Rangwert von einer anderen Abfrage zurückkehrte, anstatt die Abfrage seines Lauf wird am Ende und damit Reihen hat, die wie erwartet nicht sequentiell.

NHibernate hat separate Abfrage und Entity-Caches rel="nofollow (es tatsächlich zwei Entity-Caches sind - die Sitzungscache und die < a href = "http://nhforge.org/doc/nh/en/index.html#performance-cache" rel = "nofollow noreferrer"> Second-Level-Cache-Einheit ) und hängen die Auswirkungen auf welche sind verwendet werden.

Wenn die Abfrage-Cache nicht aktiviert ist, kann eine falsche Rangwerte empfangen werden, wenn Sie machen zwei unterschiedliche Abfragen innerhalb der gleichen Sitzung, die ein Ergebnis teilen, aber mit verschiedenen Reihen. In diesem Fall überschreibt die zweite Abfrage der gleichen Sitzung wird nicht die Objektdaten bereits in der Sitzung von der ersten Abfrage (da es für die Einheit der Arbeit verändert haben könnte), so dass der Rangwert zurückgegeben wird das gleiche von den ersten sein Abfrage statt der tatsächlichen Rang aus der zweiten Abfrage. Evicting die Ergebnisse aus der ersten Abfrage sollte vermeidet dieses Problem (aber nicht die empfohlene Lösung, siehe unten)

Wenn die Abfrage-Cache ist aktiviert ist, können falsche Rangwerte auch empfangen werden, wenn die gleiche Abfrage zu wiederholen, nachdem eine andere Abfrage ausgeführt hat, dass ein Ergebnis mit einem anderen Rang hatte. In diesem Fall fügt die erste Ausführung der Abfrage die Ergebniskennungen zu dem Abfrage-Cache und die Entitäten (mit ihrem Rang) auf die Entität-Cache. Die verschachtelte Abfrage (wenn in einer anderen Sitzung ausgeführt werden) in einer Änderung des Rangwert führen könnte mit der Entität in der Entity-Cache gespeichert. Wenn die erste Abfrage erneut ausgeführt, werden die zwischengespeicherten Kennungen verwendet, um die zwischengespeicherten Entitäten Nachschlag (mit den geändertenen Reihen).


Das Problem vollständig durch eine Änderung der Einheit angesprochen werden kann nur auf die beharrte Werte für die Entität umfassen (das heißt ohne den Rang). Dann wird für die Abfrage, einen Vorsprung verwenden, um die Kennung und den Rang für diese Abfrage zu extrahieren:

ICriteria criteria = session.CreateCriteria(typeof(Entity));
criteria.SetCacheable(true);
criteria.SetCacheRegion("SearchResults");
criteria.SetProjection
    (Projections.Id(), 
     Projections.SqlProjection("row_number() over(order by value) as Rank",
                               new[] { "Rank" },
                               new[] { NHibernateUtil.Int32 }));

In diesem Fall, da der Rang ein Werttyp ist, wird die Abfrage-Cache speichert den Rang an der Seite des Abfrageergebnis Identifikatoren für die spezifische query. Dann wird eine zweite Abfrage, Nachschlag der Einheit Wert der projizierten Bezeichner verwenden. Der schwierige Teil ist, dass Sie ein N+1 Typ Problem vermeiden werden sollen, wenn die Einheit Abfrage durchführen, und Sie werden eine andere Datenstruktur erstellen müssen, um den Entity und den damit verbundenen Rang für diese Abfrage zu heiraten.

Es ist ein wenig ärgerlich, dass Sie zwei separate Abfragen zu verwenden, anstatt eine einzelne Abfrage, aber dies scheint der einzige Weg zu sein, um die Caches in geeigneter Weise zu verwenden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top