Corretto modello oggetto query - NHibernate

1

Stavo cercando un'alternativa a Repository Pattern e ho letto su "Query object pattern" ( link ). Tuttavia, l'implementazione fornita nel link sopra non è esattamente ciò che stavo cercando: cerco qualcosa che possa essere facilmente iniettato, facilmente testato e facilmente estensibile / modificato (vale solo per l'ultimo punto nell'implementazione del collegamento). Ho pensato un po 'e penso "ho inventato" la soluzione. Supponiamo che abbia controller BlogEntriesController (sto parlando di mvc asp applicazione con ORM) e mi inietto alla classe di costruzione:

public class BlogEntriesQueries
{
    IRetrieveQuery<BlogEntryEntity> PageBlogEntries { get; set; }
    IRetrieveQuery<BlogEntryEntity> ProposedBlogEntries { get; set; }
    IAddQuery<BlogEntryEntity> CreateNewBlogEntry { get; set; }
    ... etc..
}

dove IRetrieveQuery<T> è smth come:

public interface IRetrieveQuery<TEntity> where TEntity : EntityBase
     IQueryable<TEntity> CurrentQuery { get; }
     IRetrieveQuery<TEntity> InvokeQuery(IRetrieveQuery<TEntity> subQuery);
     IEnumerable<TEntity> GetQueryResults();
}

Quindi tutto il lavoro che dovrei fare è la corretta configurazione del contenitore IoC per iniettare query nel controller e le chiamate appropriate nel controller come: _blogQueries.ProposedBlogEntries.GetQueryResults() La domanda è - è una buona soluzione - ci sono degli svantaggi che io indosso capisci? Penso che otterrei la testabilità (non ho nemmeno bisogno di simulare ISession in caso di NHibernate ) e sarebbe facilmente estensibile, ma non sono un esperto (specialmente nelle applicazioni di database) con qualsiasi mezzo.

    
posta fex 09.08.2014 - 17:51
fonte

3 risposte

3

I test delle query possono essere gestiti facilmente senza bisogno di prenderli in giro. Hai solo bisogno di affrontarlo da una vista leggermente diversa. Esempio: qui .

La seconda cosa è: hai davvero bisogno di capacità di iniettare domande? Le query sono solitamente strettamente legate alla logica aziendale a cui sono abituate. Guadagnerai davvero qualcosa complicando la tua vita estorcendo ogni query? Ogni volta che crei un disegno, assicurati di scrivere effettivamente una quantità significativa di codice, che utilizza questo disegno, in modo da poter valutare quanto sia complesso utilizzare effettivamente il design.

Nota pratica finale: sei sicuro che le tue query funzionino sempre su una singola entità? O restituire detta entità? Le query sono in genere piuttosto complesse. Puoi semplicemente utilizzare LINQ direttamente se non hai bisogno di query complesse.

Un'altra cosa che ho notato: stai riutilizzando una singola query per tutte le chiamate? È davvero una domanda? Sembra una diversa forma di repository. Come hai intenzione di passare i parametri per la query?

    
risposta data 09.08.2014 - 23:14
fonte
2

Penso che ti potrebbe piacere il modello dell'oggetto query che ho scritto per NHibernate: link

Semplifica la creazione e il consumo dei propri oggetti di query, con supporto per la memorizzazione nella cache di "terzo livello" e la trasformazione dei risultati delle query. Fornisce un'interfaccia IDatabases, che si utilizza per richiamare query e comandi. Se si ottiene la query e gli oggetti di comando dalle classi di base fornite, è possibile eseguire chiamate fittizie all'interfaccia IDatabases nei test dell'unità.

Funziona usando un'interfaccia come questa:

public interface IDatabases
{
    ISessionManager SessionManager { get; }

    T Query<T>(IDatabaseQuery<T> query);
    T Query<T>(ICachedDatabaseQuery<T> query);

    void Command(IDatabaseCommand command);
    T Command<T>(IDatabaseCommand<T> command);
}

Data una classe di entità POCO come questa:

class Database1Poco
{
    public int Property1 { get; set; }
    public string Property2 { get; set; }
}

Puoi creare oggetti di query come questo:

class Database1PocoByProperty1 : DatabaseQuery<Database1Poco>
{
    public override Database1Poco Execute(ISessionManager sessionManager)
    {
        return sessionManager.Session.Query<Database1Poco>().SingleOrDefault(x => x.Property1 == Property1);
    }

    public int Property1 { get; set; }
}

E poi usali in questo modo:

var database1Poco = _databases.Query(new Database1PocoByProperty1 { Property1 = 1 });
    
risposta data 13.08.2015 - 21:17
fonte
1

Questa è una corretta implementazione, stai andando nella giusta direzione e non avrà effetti collaterali. Potresti voler scrivere creare un test di integrazione per assicurarti che l'API di query sia progettata secondo le tue necessità.

Rendi il più semplice possibile. Non gonfiare con pattern util ne serve uno.

    
risposta data 09.08.2014 - 21:34
fonte

Leggi altre domande sui tag