Come suggerire di utilizzare un ORM invece di stored procedure?


31

Lavoro in un'azienda che utilizza solo procedure memorizzate per tutti gli accessi ai dati, il che rende molto fastidioso mantenere sincronizzati i nostri database locali poiché ogni impegno che abbiamo per eseguire nuovi proc. Ho usato alcuni ORM di base in passato e trovo l'esperienza molto migliore e più pulita. Vorrei suggerire al responsabile dello sviluppo e al resto del team che esamineremo l'utilizzo di un ORM di qualche tipo per lo sviluppo futuro (il resto del team ha familiarità solo con le procedure memorizzate e non ha mai usato nient'altro). L'architettura attuale è .NET 3.5 scritta come .NET 1.1, con "classi god" che usano una strana implementazione di ActiveRecord e restituiscono DataSet non tipizzati che sono sottoposti a loop in file code-behind - le classi funzionano in questo modo:

class Foo { 
    public bool LoadFoo() { 
        bool blnResult = false;
        if (this.FooID == 0) { 
            throw new Exception("FooID must be set before calling this method.");
        }

        DataSet ds = // ... call to Sproc
        if (ds.Tables[0].Rows.Count > 0) { 
            foo.FooName = ds.Tables[0].Rows[0]["FooName"].ToString();
            // other properties set
            blnResult = true;
        }
        return blnResult;
    }
}

// Consumer
Foo foo = new Foo();
foo.FooID = 1234;
foo.LoadFoo();
// do stuff with foo...

Non c'è praticamente nessuna applicazione di alcun modello di progettazione. Non ci sono test di sorta (nessun altro sa come scrivere unit test e il test viene effettuato caricando manualmente il sito Web e frugando). Guardando attraverso il nostro database abbiamo: 199 tabelle, 13 viste, un enorme 926 stored procedure e 93 funzioni. Circa 30 tabelle vengono utilizzate per lavori batch o cose esterne, il resto viene utilizzato nella nostra applicazione principale.

Vale la pena perseguire un approccio diverso in questo scenario? Sto parlando di andare avanti solo perché non ci è permesso di refactoring il codice esistente poiché "funziona", quindi non possiamo cambiare le classi esistenti per usare un ORM, ma non so con quale frequenza invece aggiungiamo moduli nuovi di zecca di aggiungere / correggere i moduli attuali, quindi non sono sicuro che un ORM sia l'approccio giusto (troppo investito in stored procedure e DataSet). Se è la scelta giusta, come devo presentare il caso per usarne uno? Al di fuori della mia testa, l'unico vantaggio che mi viene in mente è avere un codice più pulito (anche se potrebbe non esserlo, dato che l'architettura attuale non costruito con gli ORM in mente, quindi fondamentalmente trufferemmo gli ORM sui moduli futuri, ma i vecchi userebbero comunque i DataSet) e meno problemi per ricordare quali script di procedura sono stati eseguiti e quali devono essere eseguiti, ecc. ma è tutto, e non so quanto sarebbe convincente un argomento. La manutenzione è un'altra preoccupazione, ma di cui nessuno, tranne me, sembra preoccuparsi.


8
Sembra che tu abbia più problemi che semplicemente convincere il team a usare gli ORM. Mi sembra che il tuo team non sia a conoscenza di alcune buone pratiche di sviluppo (ad esempio modelli di progettazione, test unitari). Queste sono le questioni più importanti che devi affrontare.
Bernard,

6
Ironia della sorte, penso che in circa 5 anni di sviluppo ho incontrato forse solo una manciata di persone / team che erano a conoscenza di cose come modelli di progettazione e test unitari; di solito sono l'unico nella compagnia che conosce queste cose.
Wayne Molina,

3
@Wayne M: Lo trovo un po 'inquietante, ma non mi sorprende neanche questo.
Bernard,

2
L'ho trovato molto ... scoraggiante. È strano quando suggerisci qualcosa e ottieni un aspetto da "cervo nei fari" che indica che l'altra persona non ha la più vaga idea di cosa tu stia parlando o perché qualcuno avrebbe mai considerato di farlo. L'ho fatto succedere parecchie volte in passato.
Wayne Molina,

2
Sono un grande fan di Stored Procedure, quindi il mio commento è parziale, ma non sono completamente d'accordo con l'intera premessa. Ti piace ORM e vuoi usarlo bene. Comunque il resto della squadra sta bene con i proc memorizzati. Perché costringerli a ciò che ti piace?
Darknight,

Risposte:


47

Le procedure memorizzate sono errate, sono spesso lente e circa efficienti quanto il normale codice lato client.

[L'accelerazione è in genere dovuta al modo in cui il client e l'interfaccia della procedura memorizzata sono progettati e al modo in cui le transazioni sono scritte come brevi e mirate esplosioni di SQL.]

Le procedure memorizzate sono uno dei posti peggiori in cui inserire il codice. Suddivide l'applicazione in due lingue e piattaforme secondo regole spesso casuali.

[Questa domanda verrà sottoposta a downgrade con un punteggio di circa -30 perché molte, molte persone ritengono che le procedure memorizzate abbiano poteri magici e debbano essere utilizzate nonostante i problemi che causano.]

Spostare tutto il codice della procedura memorizzata sul client renderà le cose molto più facili per tutti.

Occasionalmente dovrai comunque aggiornare lo schema e il modello ORM. Tuttavia, le modifiche allo schema sono isolate dalle modifiche ORM, consentendo una certa indipendenza tra le applicazioni e lo schema del database.

Sarai in grado di testare, correggere, mantenere, comprendere e adattare tutte quelle procedure memorizzate mentre le riscrivi. La tua app funzionerà allo stesso modo e diventerà molto meno fragile perché non stai più rompendo in due diverse tecnologie.

Gli ORM non sono magici e le buone capacità di progettazione del database sono assolutamente essenziali per farlo funzionare.

Inoltre, i programmi con molti client SQL possono rallentare a causa della scarsa considerazione dei limiti delle transazioni. Uno dei motivi per cui le procedure memorizzate sembrano essere veloci è che le procedure memorizzate impongono una progettazione delle transazioni molto accurata.

Gli ORM non forzano magicamente un'attenta progettazione delle transazioni. La progettazione delle transazioni deve ancora essere eseguita con la stessa cura di quando è stata scritta la stored procedure.


19
+1 perché le procedure memorizzate sono un dolore totale con cui lavorare
Gary Rowe,

3
: '(Non ho alcun problema con le procedure memorizzate. Per me è solo un altro livello di astrazione.
Mike Weller

3
Se creiamo SP, il motore di database lo memorizza come modulo compilato e crea il percorso di esecuzione in modo che venga eseguito il più velocemente possibile. Ma ORM invia SQL ogni volta che deve essere compilato ed eseguito dal motore di database. Penso che sarà più lento usare un ORM invece di Stored Procedure.
DeveloperArnab,

4
Divertente. Siamo passati da un ORM alle procedure memorizzate solo a causa di ... SPEED. Non il tempo necessario per la programmazione, ma il tempo necessario a un ORM per cose come materializzare oggetti, cercare un oggetto, aggiornarlo su client diversi. SP dove l'inferno è molto più veloce. Un esempio: leggere 30.000 oggetti da DB con un nuovo ORM moderno ha bisogno ... vabbè. timeout dopo 2 minuti. Chiamare la procedura memorizzata e ottenere il risultato - 2 secondi. Sì, esistono molti trucchi come il paging per ridurre notevolmente il callign da un DB, ma una grande differenza se sono solo che un ORM può essere utilizzato o a
Offler

2
@DeveloperArnab: Questo potrebbe essere vero 20 anni fa, ma i moderni motori DB sono piuttosto sofisticati e in grado di riconoscere le query eseguite in precedenza e riutilizzare i piani di esecuzione, la differenza di velocità al giorno d'oggi è così lieve che difficilmente merita il fastidio aggiuntivo di SP.
whatsisname

20

Le procedure memorizzate sono buone, sono veloci e molto efficienti e sono il luogo ideale in cui inserire il codice relativo ai dati. Spostare tutto quel codice sul client renderà le cose leggermente più facili per te come sviluppatore del client (leggermente, poiché dovrai ancora aggiornare lo schema e il modello ORM quando il commit lo modifica) ma perderai tutto quel codice esistente e renderai la tua app è più lenta e probabilmente più fragile considerando la perdita di tutte queste abilità sql.

Mi chiedo se i DBA siano seduti lì dicendo "oh, ogni commit, devo abbattere di nuovo il client, dovremmo invece spostare tutto il codice in moduli DB".

Nel tuo caso, dovresti essere in grado di sostituire l'ORM personalizzato esistente (ovvero le tue classi divertenti) con quello di qualcun altro senza alcuna perdita, tranne le modifiche al modo in cui il tuo codice code-behind è scritto. Puoi mantenere anche gli SP poiché la maggior parte (tutti?) Gli ORM li chiameranno felicemente. Quindi, consiglierei di sostituire quelle classi "Foo" con un ORM e andare da lì. Non consiglierei di sostituire i tuoi SP.

PS. Sembra che tu abbia un sacco di codice comune nelle classi code-behind, che li rende un modello di progettazione in sé. cosa pensi che sia in primo luogo un modello di design! (ok, potrebbe non essere il migliore, o addirittura buono, ma è ancora un DP)

Modifica: e ora con Dapper , qualsiasi motivo per evitare sprocs su un ORM pesante è sparito.


3
+1, il primo passo ovvio è passare a un ORM e usarlo per mappare i risultati delle procedure memorizzate esistenti sugli oggetti. Sbarazzati di tutta quella ds.Tables[0].Rows[0]["FooName"].ToString()merda. Il gestore ama le stored procedure? Lui riesce a tenerli. Ma sarebbe fisicamente impossibile sostenere che lo spostamento di tutto quel codice ripetitivo di tipo boilerplate in qualcosa generato da, diciamo, LINQ to SQL, fosse una cosa negativa.
Carson63000,

11
Beh, non posso credere a quanto "sbagliato" ci sia nel tuo post. Il tuo confronto con un DBA che si lamenta di dover estrarre il codice è inappropriato e completamente insensato. Innanzitutto, il database è un SERVIZIO che ha lo scopo di archiviare e recuperare i dati, fine della storia. La LOGICA come suggerisce il nome va nel livello della logica di business, che fa parte del codice API. App più fragile che si allontana dagli sprocs? Sei serio o stai solo trollando? TDD un'app con logica in sprocs e dimmi quanto è divertente. Inoltre, gli ORM non devono essere commutati. I database sono, poiché sono solo un SERVIZIO.
Matteo Mosca,

5
Non riesco davvero a capire perché alcune persone pensano che il database sia una sorta di terra santa dove tutto è sacro. Pensaci. Quando una società di terze parti ti espone un servizio, ti danno accesso diretto al loro db o lo mascherano dietro un'API? Per usare un esempio popolare, prendi qualsiasi servizio Google. Tu, sviluppatore, ti connetti alla loro API pubblica, non sai nemmeno quale database è sotto di esso o se c'è un database. Ecco come si progetta un software solido e disaccoppiato. I database non sono accessibili direttamente dalle applicazioni. I livelli medi sono lì per quello.
Matteo Mosca,

5
@Matteo Mosca: certo, ma come fa il middleware ad accedere al DB ... è un client per il DB. "client" non significa "GUI" o "app desktop". Esistono molte aree grigie nei livelli dell'applicazione: metti la convalida nella GUI o nella logica server / business? Dovrebbe andare nel server per essere un design pulito, ma sarà davvero scarso per prestazioni e reattività dell'utente. Allo stesso modo, spesso si inserisce un po 'di logica nel DB quando migliora le prestazioni e (in questo caso) la correttezza dei dati.
gbjbaanb,

4
Mi dispiace ma non sono ancora d'accordo. Il giorno in cui devi distribuire la tua applicazione in un ambiente diverso, dove non hai la stessa tecnologia DB che hai usato, ti ritrovi in ​​una situazione in cui la tua app non può essere eseguita perché non hai tutti quegli sprocs sul nuovo database .. e anche se li ricrea (che è un dolore totale) potrebbero essere diversi, a causa delle differenze dei dialetti SQL, ecc. Un'API centralizzata con logica e convalida, esposta attraverso uno standard (come SOAP o REST) ​​risolve questo problema e aggiunge testabilità, controllo delle versioni e coerenza.
Matteo Mosca,

13

Sembra che tu stia cercando di guidare il tuo team da un estremo (procedure memorizzate e set di dati) a un altro (un ORM completo). Penso che ci siano altre modifiche più incrementali che puoi impostare sull'implementazione per migliorare la qualità del codice del tuo livello di accesso ai dati, che il tuo team potrebbe essere più disposto ad accettare.

Il codice di implementazione del record attivo semi-cotto che hai pubblicato non è particolarmente elegante - ti consiglierei di ricercare il modello di repository che è facile da capire e implementare ed è molto popolare tra gli sviluppatori .NET. Questo modello è spesso associato agli ORM ma è altrettanto facile creare repository usando ADO.NET semplice.

Per quanto riguarda DataSet's - schifo! Le librerie di classi saranno molto più facili da utilizzare se si restituiscono oggetti digitati staticamente (o addirittura dinamici). Credo questa illustrazione spieghi la mia opinione sul DataSet meglio di quanto potessi.

Inoltre, puoi abbandonare i proc memorizzati senza passare a un ORM: non c'è niente di sbagliato nell'usare SQL con parametri. In effetti, lo preferirei sicuramente all'uso dei proc memorizzati a meno che tu non abbia procedure complesse che risparmiano su più round trip sul server. Anch'io lo odio quando apro un database legacy e vedo un elenco infinito di procedure CRUD.

Non scoraggio l'uso degli ORM, in genere li utilizzo sulla maggior parte dei progetti su cui lavoro. Tuttavia, riesco a capire perché potrebbe esserci un grande attrito nel provare a introdurne uno in questo progetto e nel tuo team che, per dirla in modo gentile, sembra che abbiano smesso di imparare cose nuove circa 8 anni fa. Detto questo, darei sicuramente un'occhiata alla nuova generazione di "Micro ORM" come Dapper (utilizzato per alimentare questo sito non meno) e Massive , che sono entrambi incredibilmente facili da usare e ti tengono più vicino all'SQL di un tipico ORM, e che il tuo team potrebbe essere più disposto ad accettare.


2
Penso che il problema sia proprio quando l'app è stata scritta non c'erano veri e propri ORM di nota per .NET, quindi è stato fatto nell'altro modo (il modo ASP.NET 1.1) e nessuno ha mai pensato di farlo (o qualsiasi altra cosa) in modo diverso fino a quando mi sono iscritto qualche mese fa.
Wayne Molina,

1
+1 per Dapper. Ho appena iniziato a usarlo su un progetto ed è estremamente facile da implementare e utilizzare. Sono già un grande fan.
SLoret,

4

Sono in una situazione simile, in realtà il nostro hardware, potenza e politica si appoggiano al lato del database, quindi tutto passa attraverso una procedura memorizzata. Sfortunatamente, sono una seccatura per un programmatore, specialmente quando si tratta di metadati e generazione di codice, in quanto non ci sono metadati ricchi nelle procedure memorizzate come le tabelle.

Indipendentemente da ciò, è ancora possibile scrivere codice elegante e pulito utilizzando i processi memorizzati. Attualmente sto implementando il modello di repository con tutte le procedure memorizzate. Suggerirei di guardare FluentAdo.net per la sua brillante idea quando si esegue la mappatura da Datareader ai tuoi oggetti aziendali. Ho preso un pezzo di quell'idea e l'ho riproposto per la mia soluzione fatta in casa.


3

JFTR - Sono uno sviluppatore modesto di PHP, ma sembra una questione prevalentemente politica.

Data la scala del "marciume" che sostiene l'app, allora - le migliori pratiche a parte - ci sarebbe un notevole sovraccarico per sradicarlo. Sembra che stia confinando con il territorio di riscrittura.

Potete garantire che l'alternativa che suggerite produrrebbe benefici per giustificare il costo per l'azienda? Sospetto che il ROI di questa impresa possa essere difficile da vendere all'azienda. A meno che l'app non sia instabile o non sia possibile dimostrare il merito della revisione in termini finanziari, questo potrebbe rivelarsi difficile.

ORM è l' unica alternativa a SPROCS? Esistono un paio di modelli di progettazione tra un ORM completo e SQL vaniglia. Forse potresti iniziare il processo portando gradualmente questi SPROC dal DB in un DBAL. Naturalmente c'è il pericolo che questo si trasformi in un ORM homebrew nel tempo, ma avresti fatto un passo in avanti verso l'obiettivo.


2

Siamo passati da SP a ORM alcuni anni fa.

In un caso abbiamo dovuto aggiornare 80 tabelle. Il vecchio modello di stima avrebbe stimato 80 ore per questo con entlib e SP. L'abbiamo fatto in 10 :)

Ci ha consentito una riduzione dell'80% del tempo impiegato per lo sviluppo del livello di accesso ai dati.


1
E non hai potuto scrivere l'aggiornamento della tabella perché?
Darknight,

Questo stava prendendo in memoria un oggetto complesso e lo salvava in un database relazionale per il reporting. Abbiamo scritto un programma che ha fatto una riflessione sull'oggetto per creare la struttura della tabella.
Shiraz Bhaiji,

-1

Mi sembra più che il problema di fondo sia che le tue distribuzioni non funzionino correttamente e automaticamente.

Potrebbe essere più semplice impostare un motore di generazione continua che sappia come manipolare i database secondo necessità dopo ogni commit.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.