2010-10-21 13 views
7

Normalerweise würde ich meine Kriterien/HQL Abfragen in einem Repository/dal-Klasse im Zusammenhang mit der Entität, aber in letzter Zeit habe ich darüber nachgedacht, eine weitere Abstraktion, was eine Abfrage darstellt, dies würde mir die geben Möglichkeit, allen Abfragen (z. B. Seitennummerierung) in einer Basisklasse allgemeines Verhalten hinzuzufügen.Modellierung NHibernate Abfragen

das sind jetzt meine Komponenten;

generische Schnittstelle nicht zu nhibernate bezogen werden:

public interface IQuery<T> 
{ 
    IList<T> List(); 
    T Single(); 
} 

Beispiel Implementierung einer Criteria Abfrage, etwas Ähnliches könnte mit einer HQL-Abfrage oder einer nhibernate-Linq-Abfrage

public abstract class CriteriaQuery<T>: IQuery<T> 
{ 
    [Inject] 
    public ISessionFactory SessionFactory { protected get; set; } 

    protected ISession Session 
    { 
     get { return SessionFactory.GetCurrentSession(); } 
    } 

    protected abstract ICriteria Configure(ICriteria criteria); 

    [Transaction] 
    public virtual IList<T> List() 
    { 
     var criteria = Session.CreateCriteria(typeof (T)); 

     return Configure(criteria) 
       .List<T>(); 
    } 

    [Transaction] 
    public virtual T Single() 
    { 
     return Configure(Session.CreateCriteria(typeof(T))) 
       .UniqueResult<T>(); 
    } 
} 

und getan wird Hier würde eine domänenspezifische Abfrage wie folgt aussehen:

public interface IGetVideosQuery: IQuery<Video> 
{ 
    IGetVideosQuery Page(int index); 
    IGetVideosQuery PageSize(int pageSize); 

    IGetVideosQuery AllTime { get; } 
    IGetVideosQuery Today { get; } 
    IGetVideosQuery LastWeek { get; } 
} 

any Gedanken dazu? mögliche Probleme, auf die ich stoßen könnte? Danke!

+1

Check out Fabio Maulo 'erweiterte' Abfrage-Objekt für ein etwas verwandtes Konstrukt: http://fabiomaulo.blogspot.com/2010/07/enhanced-query-object.html – DanP

+0

@ danp: danke dafür! –

Antwort

2

Mein erster Vorschlag wäre, mit Linq2NH zu gehen, verfügbar in NHibernate 2.1 und darüber hinaus. Die Sitzung stellt eine AsQueryable<T>() Methode zur Verfügung, auf der Sie eine Linq-Abfrage erstellen können. Dadurch können Sie Kriterien und Projektionen nach Belieben mit den Linq-Erweiterungsmethoden hinzufügen, einschließlich Skip() und Take() zur Implementierung der Paginierung (myQuery.Skip(PageIdx*PageSize).Take(PageSize).ToList()) und zu filternden Where-Klauseln. Die in diesen Abfragen verwendeten Lambdas und Variablen könnten in einer Art der QueryInfo-Klasse gekapselt werden, was wiederholbare persistente Abfragen ermöglicht.

4

Ich nahm einen anderen Weg, der von CQS. Was das bedeutet ist, dass es meine mutierende Logik von meiner Abfragelogik trennt.

Nun gibt es verschiedene Ideen, wie dies zu implementieren, und ich wählen Sie diese ein:

  • Alle meine Mutation Logik ist wie DeactivateUser und ChangeRelationAddress Befehl aktiviert werden. Für diese Geschäftslogik habe ich normale Repositories wie Sie beschreiben;

  • Für die Anzeige von Daten verwende ich ein komplett verwaltetes System. Mit diesem System beschreibe ich Abfragen wie die Specification Pattern. Ich beschreibe die Basistabelle und die Felder. Das Abfragesystem erstellt automatisch die Joins für mich und mit Filterdefinitionen biete ich Filter an.

Dieses System ermöglicht es mir, die Komplexität meiner Repositories zu halten, weil ich denken nicht über filtert ein Benutzer s eingestellt oder ORDER BY‘kann. Das System, das diese Daten anzeigt, erstellt automatisch die Filter unter Verwendung von Criteria und behandelt das Paging für mich.

Vielleicht kann ein solches System für Sie arbeiten.