2

Ich habe eine Einheit:Nhibernate 2. Ebene Cache mit AliasesToBean Transformator

public class SalesUnit 
{ 
    public virtual long Id { get; set; } 
    public virtual string Name { get; set; } 

} 

und damit verbundene Dto:

public class SalesUnitDto 
{ 
    public long Id { get; set; } 
    public string Name { get; set; } 

} 

Ich habe eine sehr einfache Abfrage haben:

SalesUnitDto result = null; 
var list = _session.QueryOver<SalesUnit>() 
       .SelectList(l => l 
        .Select(x => x.Id).WithAlias(() => result.Id) 
        .Select(x => x.Name).WithAlias(() => result.Name)) 
       .TransformUsing(Transformers.AliasToBean<SalesUnitDto>()) 
       //.Cacheable() 
       .List<SalesUnitDto>(); 

Es funktionierte bis ich den Cache der zweiten Ebene eingesteckt habe. Also, wenn ich Cacheable() Zeile auskommen bekomme ich die Ausnahme:

Nachricht: Wert kann nicht null sein. Parametername: Aliase Stacktrace:

at NHibernate.Transform.AliasedTupleSubsetResultTransformer.IncludeInTransform(String[] aliases, Int32 tupleLength) 
    at NHibernate.Transform.CacheableResultTransformer.Create(ITupleSubsetResultTransformer transformer, String[] aliases, Boolean[] includeInTuple) 
    at NHibernate.Loader.Loader.GenerateQueryKey(ISessionImplementor session, QueryParameters queryParameters) 
    at NHibernate.Loader.Loader.ListUsingQueryCache(ISessionImplementor session, QueryParameters queryParameters, ISet`1 querySpaces, IType[] resultTypes) 
    at NHibernate.Impl.SessionImpl.List(CriteriaImpl criteria, IList results) 

Also, was ist daran falsch? Ist es ein Fehler von NHibernate? Ich habe verschiedene Anbieter ohne Erfolg ausprobiert. CacheableResultTransformer wie dies auch habe ich versucht, zu erstellen:

CacheableResultTransformer.Create(Transformers.AliasToBean<SalesUnitDto>(), new[] { "Id", "Name" }, new[] { true, true }) 

Es kann zurückkehren und Daten-Cache, sondern nur als Tupel (Objekt []). Ich habe es nicht geschafft, Dto zurückzugeben.

Hier ist das Arbeitsbeispiel, ein Problem zu demonstrieren: github

+0

Wie wird 'result' deklariert? –

+0

@Andrew Whitaker, 'Ergebnis' ist' SalesUnitDto' –

+0

Kann nicht reproduzieren - arbeitet mit oder ohne 'Cacheable()'. NH v4.0.4.4000 –

Antwort

2

Es stellt sich heraus, um einen Fehler/Einschränkung von (N) Hibernate sein. Wenn das Zwischenspeichern aktiviert ist, beginnt das Original IResultTransformernullstring[] aliases Argument, das für AliasToBeanTransformer Implementierung erforderlich ist, daher die Ausnahme, die Sie erhalten.

Als Abhilfe könnte ich die folgende benutzerdefinierte Erweiterungsmethode und Transformator vorschlagen, die die aktuellen Aliase speichert, wenn sie aufgerufen und übergibt sie an die zugrunde liegende AliasToBeanTransformer, wenn das übergebene Argument null ist:

public static class NHExtensions 
{ 
    public static IQueryOver<TRoot, TSubType> TransformUsingAliasToBean<TRoot, TSubType>(this IQueryOver<TRoot, TSubType> query, Type resultType) 
    { 
     ITupleSubsetResultTransformer resultTransformer = new AliasToBeanResultTransformer(resultType); 
     var criteria = query.UnderlyingCriteria as NHibernate.Impl.CriteriaImpl; 
     if (criteria != null) 
      resultTransformer = new CacheableAliasToBeenResultTransformer(resultTransformer, criteria.Projection.Aliases); 
     return query.TransformUsing(resultTransformer); 
    } 

    class CacheableAliasToBeenResultTransformer : ITupleSubsetResultTransformer 
    { 
     ITupleSubsetResultTransformer baseTransformer; 
     string[] aliases; 

     public CacheableAliasToBeenResultTransformer(ITupleSubsetResultTransformer baseTransformer, string[] aliases) 
     { 
      this.baseTransformer = baseTransformer; 
      this.aliases = aliases; 
     } 

     public bool[] IncludeInTransform(string[] aliases, int tupleLength) 
     { 
      return baseTransformer.IncludeInTransform(aliases ?? this.aliases, tupleLength); 
     } 

     public bool IsTransformedValueATupleElement(string[] aliases, int tupleLength) 
     { 
      return baseTransformer.IsTransformedValueATupleElement(aliases ?? this.aliases, tupleLength); 
     } 

     public IList TransformList(IList collection) 
     { 
      return baseTransformer.TransformList(collection); 
     } 

     public object TransformTuple(object[] tuple, string[] aliases) 
     { 
      return baseTransformer.TransformTuple(tuple, aliases ?? this.aliases); 
     } 
    } 
} 

und Sie fragen würde be:

SalesUnitDto result = null; 
var list = _session.QueryOver<SalesUnit>() 
    .SelectList(l => l 
     .Select(x => x.Id).WithAlias(() => result.Id) 
     .Select(x => x.Name).WithAlias(() => result.Name)) 
    .TransformUsingAliasToBean(typeof(SalesUnitDto)) 
    .Cacheable() 
    .List<SalesUnitDto>(); 

Getestet und funktioniert für dieses Szenario. Natürlich kann ich nicht garantieren, dass es für alle QueryOver Variationen funktioniert.

1

Dieser Fehler von NHibernate ist behoben in v4.1.0.4000!

+0

Danke a Viel Bruder, du bist großartig! – vaqifrv

+0

Leider haben einander mit MaxAliastLength auf ausgewählten Dialekt eingeführt und alle meine Integration Tests mit SQLite-Treiber schlägt fehl. :( – dariol

Verwandte Themen