2012-01-16 11 views
10

Quindi ho sviluppato con Entity + LINQ per un po 'e sto davvero iniziando a chiedermi le migliori pratiche. Sono abituato al modello di "se ho bisogno di ottenere dati, riferimento a una stored procedure". Le stored procedure possono essere modificate al volo se necessario e non richiedono la ricompilazione del codice. Ho constatato che le mie domande nel mio codice stanno cercando in questo modo:In che modo utilizzare Entity + LINQ non è solo una codifica essenzialmente difficile delle mie query?

List<int> intList = (from query in context.DBTable 
        where query.ForeignKeyId == fkIdToSearchFor 
        select query.ID).ToList(); 

e sto iniziando a chiedersi quale sia la differenza tra questo e questo:

List<int> intList = SomeMgrThatDoesSQLExecute.GetResults(
            string.Format("SELECT [ID] 
               FROM DBTable 
               WHERE ForeignKeyId = {0}", 
            fkIdToSearchFor)); 

La mia preoccupazione è che quello Sono essenzialmente difficile codificare la query nel codice. Mi sto perdendo qualcosa? È questo il punto di Entità? Se ho bisogno di fare qualche domanda reale, dovrei metterlo in un sproc?

+0

La seconda query non è una 'stored procedure'. La stored procedure verrà scritta all'interno del tuo database e il codice Entity lo chiamerà semplicemente. Invece di scrivere la frase select, scrivi il nome della stored procedure –

+0

Sono consapevole che non è una stored procedure. Sto cercando di far notare che se faccio una query LINQ su un contesto di entità, sembra esattamente la stessa cosa se ho appena codificato la query SQL nel codice. – jermny

+2

Mi sono sempre chiesto questo. Sarebbe interessato a vedere la risposta! –

risposta

10

Personalmente evito di eseguire richieste SQL hard-code (come secondo esempio). Scrivendo LINQ invece di SQL attuale permette:

  • facilità d'uso (Intellisense, tipo di controllo ...)
  • potere del linguaggio LINQ (che è il più delle volte più semplice di SQL quando c'è una certa complessità, più join ... ecc.)
  • potere di anonymous types
  • vedendo gli errori in questo momento a tempo di compilazione, non durante il runtime due mesi dopo ...
  • meglio refactoring se il vostro desidera rinominare una tabella/colonna/... (hai vinto' t dimenticare di rinominare qualsiasi cosa con LINQ per i controlli in fase di compilazione)
  • accoppiamento libero tra le tue richieste e il tuo database (cosa succede se passi da Oracle a SQL Server? Con LINQ non cambierai il tuo codice, con richieste hardcoded tu Dovremo rivedere tutte le vostre richieste)
  • LINQ vs stored procedure: inserite la logica nel vostro codice, non nel vostro database. Vedi la discussione here.

se è necessario ottenere dati, fare riferimento a una stored procedure. Le stored procedure possono essere modificati al volo, se necessario, e non richiedono il codice ricompilazione

-> se è necessario aggiornare il vostro modello, probabilmente hanno anche per aggiornare il codice per prendere l'aggiornamento del DB in considerazione. Quindi non penso che ti aiuterà a evitare una ricompilazione la maggior parte del tempo.

+0

Ok, stavo scrivendo questo, grande qualcuno l'ha fatto. – ivowiblo

11

La potenza di Linq non si rende evidente fino a quando non sono necessarie query più complesse.

Nel tuo esempio, pensa a cosa avresti bisogno di fare se volessi applicare un filtro di qualche forma alla tua query. Utilizzando l'SQL costruito su stringhe, è necessario aggiungere i valori in un generatore di stringhe, protetto dall'iniezione SQL (o passare allo sforzo aggiuntivo di preparare l'istruzione con i parametri).

Supponiamo di volere aggiungere una dichiarazione alla query linq;

IQueryable<Table> results = from query in context.Table 
          where query.ForeignKeyId = fldToSearchFor 
          select query; 

Puoi prenderlo e farlo;

results.Where(r => r.Value > 5); 

La sql risultante sarebbe simile;

SELECT * FROM Table WHERE ForeignKeyId = fldToSearchFor AND Value > 5 

Fino a quando si enumera il set di risultati, le eventuali condizioni aggiuntive si desidera decorare avranno aggiunto in per voi, risultando in un modo molto più flessibile e potente per fare query dinamiche. Io uso un metodo come questo per fornire filtri in una lista.

+0

È un buon punto, ma mi chiedo se la facilità d'uso sia più importante rispetto alle query versatili. È più importante avere la comodità delle query LINQ al costo di averli codificati nell'applicazione, forzando gli aggiornamenti quando tali query cambiano anche leggermente? – jermny

+1

Ho creato repository che restituiscono sempre SELECT * FROM Table. Applico uno strato di "diritti di accesso" dalla mia applicazione tra questo e lo sviluppo normale, perché voglio eliminare lo sviluppo. Utilizzando questo metodo, continuo a fornire allo sviluppatore la possibilità di manipolare ulteriormente la query, aggiungendo i propri filtri. – Hammerstein

5

Sì, se sei bravo in SQL, puoi ottenere tutto ciò con i proc memorizzati e beneficiare di prestazioni migliori e alcuni vantaggi di manutenzione.

D'altra parte, LINQ è di tipo sicuro, leggermente più facile da usare (come gli sviluppatori sono abituati da scenari non-db) e può essere utilizzato con diversi provider (può tradurre in codice specifico del provider) . Tutto ciò che implementa IQueriable può essere utilizzato allo stesso modo con LINQ.

Inoltre, è possibile passare le query parzialmente costruite in giro e saranno pigre valutate solo quando necessario.

Quindi, sì, voi sono codificandoli con difficoltà, ma, in sostanza, è la logica del vostro programma, ed è codificato in modo rigido come qualsiasi altra parte del vostro codice sorgente.

5

LINQ sta codificando tutte le query nell'applicazione? Si assolutamente.

Consideriamo cosa significa per la vostra applicazione.

Se si desidera modificare il modo in cui si ottengono alcuni dati, è necessario apportare una modifica al codice compilato; non puoi fare un "hotfix" al tuo database.

Tuttavia, se si modifica una query a causa di una modifica nel modello di dati, è probabile che si debba modificare il modello di dominio per adattarlo alla modifica.

Supponiamo che il modello non sia stato modificato e che la query stia cambiando perché è necessario fornire ulteriori informazioni alla query per ottenere il risultato corretto. Questo tipo di modifica richiede sicuramente la modifica dell'applicazione per consentire l'utilizzo del nuovo parametro per aggiungere ulteriori filtri alla query.

Ancora una volta, supponiamo che tu sia felice di utilizzare un valore predefinito per il nuovo parametro e che l'applicazione non debba specificarlo. La query potrebbe includere un campo come parte del risultato. Non devi tuttavia utilizzare questo campo aggiuntivo e puoi ignorare le informazioni aggiuntive inviate via cavo. Qui è stato introdotto un po 'di problemi di manutenzione, in quanto l'SQL non è in linea con l'interpretazione della sua applicazione.

In questo scenario specifico in cui non si sta apportando una modifica esterna alla query o l'applicazione ignora le modifiche, si ottiene la possibilità di distribuire le modifiche solo SQL senza dover toccare l'applicazione o abbattilo per un po 'di tempo (o se ti piacciono i desktop, distribuisci una nuova versione).


Realisticamente, quando si tratta di fare modifiche a un sistema, la maggior parte del vostro tempo sta per essere speso progettare e testare le vostre domande, non distribuirli (e se non lo è, allora si Sei in un posto spaventoso). Il vantaggio di avere una query in LINQ è quanto è più facile scriverli e testarli separatamente da altri fattori, come test unitari o parte di altri processi.

L'unico motivo reale per utilizzare stored procedure su LINQ è se si desidera condividere il database tra diversi sistemi utilizzando un'API coerente a livello di SQL. È una situazione piuttosto orribile e preferirei sviluppare un livello di servizio sopra il database SQL per uscire da questo progetto.

+0

Sono d'accordo con i tuoi sentimenti. Tuttavia, c'è qualcosa da dire per avere un database autoconsistente a cui si possa accedere direttamente senza alcun pericolo di vera inconsistenza. (vale a dire vincoli o trigger che applicano tutte le regole di coerenza che sono fondamentali per i dati.) Questo perché il database potrebbe sopravvivere al livello di servizio originale che lo utilizzava. Non consiglio l'accesso al database direttamente se un livello di servizio è stato aggiunto, ma idealmente farlo non dovrebbe essere pericoloso. –

+1

Non direi che i vincoli (e in misura minore, i trigger) sono strumenti da buttare via. Sono una parte essenziale dell'integrità dei dati e l'integrità dei dati è la responsabilità principale del database. –

+0

Buono. Molte persone che usano gli ORM amano semplicemente mantenere l'integrità nel codice. Quando non si utilizza un livello di servizio condiviso che è distasterous, ma quando si utilizza uno, è spesso possibile farla franca.Se sto capendo correttamente: Accetti quindi che il databsse sia responsabile per l'archiviazione e l'integretria e se si desidera un'API comune al database per più applicazioni, un livello di servizio è preferibile a migliaia di stored procedure. Questo ha senso per me. –

3

Mi sono anche chiesto di questo, ma la mentalità che database di interattività è solo nel database livelloè un concetto obsoleto. Avere un dba dedicato sforna le stored procedure mentre gli sviluppatori di front-end multipli attendono, è davvero un uso inefficiente dei dollari di sviluppo.

I negozi Java si attengono a questo paradigma perché non hanno uno strumento come linq e si attengono a tale paradigma per necessità. I database con .Net scoprono che la necessità di una persona del database viene insegnata se non completamente rimossa perché una volta posizionata la struttura i dati possono essere manipolati in modo più efficiente (come mostrato da tutti gli altri risponditori di questo post) nel livello dati utilizzando linq anziché da SQL raw.

Se uno ha la possibilità di utilizzare code first e creare un modello di database da zero, dando vita all'attuale classi di entità prima nel codice e quindi eseguire EF a fare la magia della realtà creazione del database ... si capisce come il database sia veramente uno strumento che memorizza i dati e la necessità di stored procedure e un dba dedicato non è necessario.

+3

Nella mia esperienza, il database in qualsiasi sistema di grandi dimensioni è di solito il collo di bottiglia delle prestazioni e quindi è fondamentale garantire che le query siano performanti e ottimizzate in modo appropriato. Il che significa che qualcuno che è orientato al database è fondamentale se vuoi scalare. La mia preoccupazione è sempre, che se il db viene trattato come un cittadino di 2a classe, allora prima o poi ti morderà quando si comporta male. – AdaTheDev

+1

@AdaTheDev (* Ho fatto qualche ripresa negli anni '80 *). Sono d'accordo con te. Qualsiasi tecnologia può rapidamente entrare nelle erbacce. Proprio come il paradigma del codice macchina in cui un programma in un linguaggio avanzato che crea il codice macchina, non sarà veloce come il codice assembly modificato. Ma il compromesso è lì per tempo per completare la velocità dei versi; lo stesso vale quando si usa linq. – OmegaMan

+0

sì, non posso discuterne - sicuramente migliora la produttività, quindi posso vedere dei benefici lì. Anche se trovarlo è in conflitto con il mio database interno-geek! – AdaTheDev

Problemi correlati