Domanda

Un progetto a cui sto lavorando al momento coinvolge il refactoring di un C# Oggetto Com che serve di una banca dati a livello di accesso per alcuni Sql 2005 database.

L'autore del presente codice ha costruito tutte le query sql manualmente utilizzando una stringa, e molti se-istruzioni per costruire abbastanza complessa istruzione sql (~10 join >10 sub seleziona, ~15-25 dove le condizioni e GroupBy s).La tabella di base è sempre la stessa, ma la struttura di join, le condizioni e i raggruppamenti dipendono da un insieme di parametri che vengono passati nella mia classe/metodo.

La costruzione di query sql come funziona, ma è evidente che non è molto elegante soluzione (e piuttosto difficile da leggere/comprendere e mantenere così)...Potrei scrivere un semplice "generatore" di me stesso, ma sono abbastanza sicuro che io non sono il primo con questo tipo di problema, quindi le mie domande:

  • Come fare si costruire le query di database?
  • Non C# offrono un modo semplice per costruire dinamicamente la query?
È stato utile?

Soluzione

Ho usato C# e Linq per fare qualcosa di simile per ottenere voci del registro di filtrare l'input dell'utente (vedere Condizionale Query Linq):

IQueryable<Log> matches = m_Locator.Logs;

// Users filter
if (usersFilter)
    matches = matches.Where(l => l.UserName == comboBoxUsers.Text);

 // Severity filter
 if (severityFilter)
     matches = matches.Where(l => l.Severity == comboBoxSeverity.Text);

 Logs = (from log in matches
         orderby log.EventTime descending
         select log).ToList();

Edit:La query non viene eseguita fino a quando .ToList() nell'ultima dichiarazione.

Altri suggerimenti

A meno che non executiontime è davvero importante, vorrei prendere in considerazione il refactoring la logica di business (spesso) tende a trovare la sua strada verso il datalayer e in gazillion-lungo stored procedure.In termini di maintainabillity, editabillity e appendabillity cerco sempre (come il programmatore in C# sono) sollevare codice fino al businesslayer.

Cercando di risolvere qualcuno elses 8000 linea di SQL Script non è il mio preferito compito.

:)

//W

LINQ è il modo per andare.

Questo è il modo in cui mi piacerebbe farlo:

public IQueryable<ClientEntity> GetClients(Expression<Func<ClientModel, bool>> criteria)
    {
        return (
            from model in Context.Client.AsExpandable()
            where criteria.Invoke(model)
            select new Ibfx.AppServer.Imsdb.Entities.Client.ClientEntity()
            {
                Id = model.Id,
                ClientNumber = model.ClientNumber,
                NameFirst = model.NameFirst,
                //more propertie here

            }
        );
    }

Il Espressione parametro si passa sarà la query dinamica potrete costruire con le diverse clausole WHERE, JOIN, etc.Questa Espressione si ottiene Richiamato in fase di esecuzione e darti ciò di cui hai bisogno.

Ecco un esempio di come chiamarlo:

public IQueryable<ClientEntity> GetClientsWithWebAccountId(int webAccountId)
    {
        var criteria = PredicateBuilder.True<ClientModel>();
        criteria = criteria.And(c => c.ClientWebAccount.WebAccountId.Equals(webAccountId));
        return GetClients(criteria);
    }

Vale la pena prendere in considerazione se si può implementare come parametrizzare contenute procedura e ottimizzare il database, piuttosto che la generazione dinamica di SQL tramite LINQ o un ORM, in fase di runtime.Spesso questo funzionerà al meglio.So che è un po ' vecchio stile, ma a volte è l'approccio più efficace.

Posso capire il potenziale di Linq, ma devo ancora vedere qualcuno provate a fare una query Linq della loro complessità, che Ben sta suggerendo

abbastanza complesse istruzione sql (~10 join >10 sub seleziona, ~15-25 dove le condizioni e GroupBy s)

Qualcuno ha esempi di grande query Linq, e qualsiasi commento sulla loro gestibilità?

Sto arrivando a questo fine e non hanno alcuna possibilità per un upvote, ma c'è una soluzione che non ho ancora visto e considerato:Una combinazione di procedura/funzione con linq-to-oggetto.O xml o datatable suppongo.

Ho questo esattamente in questa situazione, con una massiccia costruiti dinamicamente la query che era nei un risultato impressionante, ma la cui complessità fatto per un mantenimento incubo.Ho avuto così tante green commenti per aiutare i poveri sap che doveva venire dopo, e lo capisco.Ero in asp classico quindi ho avuto poche alternative.

Quello che ho fatto dal momento che è una combinazione di funzione/procedura e linq.Spesso il totale complessità è inferiore alla complessità di cercando di fare un unico luogo.Passano alcuni criteri per l'UDF, che diventa molto più gestibile.Questo vi dà una ragionevole e comprensibile set di risultati.Applicare le restanti distinzioni utilizzo di linq.

È possibile utilizzare i vantaggi di entrambi:

  • Ridurre il totale di record per quanto possibile che sul server;ottenere come molti pazzo unisce preso cura di server.I database sono buona a questo roba.
  • Linq (ad oggetto etc.) non è così potente, ma è ottimo per esprimere la complessità di criteri;in modo da utilizzare per i vari possibili distinzioni che aggiungono complessità al codice, ma che il db non sarebbe molto meglio al trattamento.Operativo ridotto, normalizzato set di risultati, linq può esprimere complixity senza molto le prestazioni.

Come decidere quali criteri per gestire il db e che con linq?Usare il vostro giudizio.Se è possibile gestire in modo efficiente i complessi query al db, è in grado di gestire questo.Parte di arte e scienza.

Si potrebbe considerare di LINQ o di un o/R Mapper come questo: http://www.llblgen.com/

Se si utilizza C# e .NET 3.5, con l'aggiunta di MS SQL Server, quindi, LINQ to SQL è sicuramente la strada da percorrere.Se si utilizza qualcosa di diverso che combinazione, io consiglierei un ORM percorso, come nHibernate o Subsonico.

C'è un tipo di sperimentale provare presso un Generatore di classe a http://www.blackbeltcoder.com/Articles/strings/a-sql-querybuilder-class.Potrebbe essere la pena dare un'occhiata.

Check out http://sqlom.sourceforge.net.Io credo che sia esattamente quello che stai cercando.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top