Disegni e pratiche per evitare voci null errate dal database


9

Una parte del mio programma recupera i dati da molte tabelle e colonne nel mio database per l'elaborazione. Alcune colonne potrebbero essere null, ma nel contesto di elaborazione corrente si tratta di un errore.

Questo "teoricamente" non dovrebbe accadere, quindi se lo fa punta a dati errati o ad un bug nel codice. Gli errori hanno gravità diverse, a seconda del campo null; vale a dire che per alcuni campi l'elaborazione dovrebbe essere interrotta e qualcuno notificato, per altri dovrebbe essere consentito il proseguimento e informare qualcuno.

Esistono buoni principi di architettura o design per gestire le nullvoci rare ma possibili ?

Le soluzioni dovrebbero essere possibili da implementare con Java ma non ho usato il tag perché penso che il problema sia in qualche modo indipendente dal linguaggio.


Alcuni pensieri che ho avuto me stesso:

Utilizzando NOT NULL

Il più semplice sarebbe usare un vincolo NOT NULL nel database.

Ma cosa succede se l'inserimento originale dei dati è più importante di questa fase di elaborazione successiva? Quindi, nel caso in cui l'inserto inserisse un a nullnella tabella (o a causa di bug o forse anche per qualche motivo valido), non vorrei che l'inserimento fallisse. Diciamo che molte più parti del programma dipendono dai dati inseriti, ma non da questa particolare colonna. Quindi preferirei rischiare l'errore nella fase di elaborazione corrente anziché nella fase di inserimento. Ecco perché non voglio usare un vincolo NOT NULL.

Ingenuamente a seconda di NullPointerException

Potrei semplicemente usare i dati come se mi aspettassi che fossero sempre lì (e questo dovrebbe davvero essere il caso) e catturare gli NPE risultanti a un livello appropriato (ad esempio in modo che l'elaborazione della voce corrente si interrompa ma non l'intero progresso dell'elaborazione ). Questo è il principio "fail fast" e spesso lo preferisco. Se è un bug almeno ottengo un NPE registrato.

Ma poi perdo la capacità di distinguere tra vari tipi di dati mancanti. Ad esempio per alcuni dati mancanti potrei lasciarli fuori, ma per altri il trattamento dovrebbe essere interrotto e un amministratore informato.

Verifica nullprima di ogni accesso e genera eccezioni personalizzate

Eccezioni personalizzate mi consentirebbero di decidere l'azione corretta in base all'eccezione, quindi questa sembra la strada da percorrere.

Ma cosa succede se dimentico di controllarlo da qualche parte? Inoltre, ingombro il mio codice con controlli null che non sono mai o raramente previsti (e quindi sicuramente non fanno parte del flusso della logica aziendale).

Se scelgo di andare in questo modo, quali schemi sono più adatti all'approccio?


Eventuali pensieri e commenti sui miei approcci sono i benvenuti. Anche soluzioni migliori di qualsiasi tipo (schemi, principi, migliore architettura del mio codice o modelli ecc.).

Modificare:

C'è un altro vincolo, in quanto sto usando un ORM per eseguire il mapping dal DB all'oggetto di persistenza, quindi fare controlli null a quel livello non funzionerebbe (poiché gli stessi oggetti sono usati in parti in cui il null non fa alcun danno) . Ho aggiunto questo perché le risposte fornite finora hanno entrambe menzionato questa opzione.


5
"Alcune delle colonne potrebbero essere nulle, ma nell'attuale contesto di elaborazione si tratta di un errore ... nel caso in cui l'inserto inserisse un valore nullo nella tabella, non vorrei che l'inserimento fallisse." Questi due requisiti sono contraddittorio. È impossibile trovare una soluzione finché non si rilassa una delle due condizioni.
Kilian Foth,

@KilianFoth Bene, il mio rilassamento è che l'errore nel contesto di "elaborazione corrente" è meno grave di quando si inserisce. Quindi accetto errori di elaborazione rari, ma voglio avere un buon design robusto per gestirli. Ecco perché NOT NULL, che altrimenti sarebbe una buona soluzione, non è possibile qui.
jhyot,

1
Se si accetta di accettare così tanti errori, i creatori di tali errori non li correggeranno mai. Se le loro dichiarazioni di inserimento disordinate hanno successo, quale incentivo hanno mai per sistemare le cose? Ritieni robusto non fallire ma accettare dati errati?
Tulains Córdova,

@ user61852 Non accetto esplicitamente gli errori ma voglio gestirli con grazia. La deglutizione di puntatori null è fuori discussione. Inoltre, cosa succede se la mia parte è davvero oggettivamente (come definita dall'azienda) meno importante di molte altre parti che richiedono l'inserimento per avere successo ma non richiedono che questo particolare campo sia impostato? Gli inserti provengono non da una voce dell'utente in cui potrei forzarli ad aggiungere il valore, ma da un altro codice in cui l'omissione è molto probabilmente un bug (ma non abbastanza importante per interrompere l'inserimento).
jhyot,

1
Contrassegnarli come NOT NULL nel database sarebbe la soluzione migliore, se una colonna è nullable, il codice dovrà gestire il caso quando lo è, anche se non è previsto perché il meccanismo di archiviazione lo consente.
Jon Raynor,

Risposte:


9

Vorrei inserire i controlli null nel codice di mappatura, in cui si crea l'oggetto dal set di risultati. Ciò mette il controllo in un posto e non consentirà al codice di arrivare a metà dell'elaborazione di un record prima di colpire un errore. A seconda di come funziona il flusso dell'applicazione, è possibile che si desideri eseguire la mappatura di tutti i risultati come fase di pre-elaborazione anziché mappare ed elaborare ogni record uno alla volta.

Se stai utilizzando un ORM, dovrai eseguire tutti i controlli null prima di elaborare ciascun record. Consiglierei un recordIsValid(recordData)metodo di tipo, in questo modo è possibile (di nuovo) tenere tutta la verifica del null e altre logiche di validazione in un unico posto. Sicuramente non mescolerei i controlli null con il resto della tua logica di elaborazione.


Grazie, questa è una buona intuizione! Sto davvero usando un ORM, quindi i controlli a quel livello non funzioneranno. Ma ho anche un po 'di mappatura su oggetti di dominio reali dagli oggetti di persistenza. Verificherò se sarebbe possibile eseguire la mappatura e la convalida in una fase di preelaborazione.
jhyot,

E se cambi il tuo ORM, e allora? Meglio difenderlo alla fonte (vedi la risposta di Doc Brown).
Robbie Dee,

@RobbieDee: non dovrebbe importare. Se devi riscrivere il codice di mappatura, allora ci sono i controlli null e li modifichi come parte della riscrittura, oppure hai un metodo separato che esegue i controlli null sui tuoi oggetti business, quindi non c'è bisogno di riscrivere. E come suggerisce Doc Brown, a volte è importante notare che mancano i dati invece di sorvolare quel fatto con un valore predefinito.
TMN,

Ciò dovrebbe accadere più in alto nel flusso ETL. Rischi ancora di duplicare gli sforzi in questo modo.
Robbie Dee,

6

Sembra che inserire un null sia un errore, ma hai paura di imporre questo errore durante l'inserimento perché non vuoi perdere dati. Tuttavia, se un campo non deve essere nullo ma lo è, stai perdendo dati . Pertanto, la soluzione migliore è garantire che i campi null non vengano salvati erroneamente in primo luogo.

A tal fine, imporre che i dati siano corretti nell'unico repository autorevole e permanente per tali dati, il database. Fallo aggiungendo vincoli non nulli. Quindi il tuo codice potrebbe non riuscire ma questi errori ti avvisano immediatamente dei bug, consentendoti di correggere i problemi che stanno già causando la perdita di dati. Ora che sei in grado di identificare facilmente i bug, prova il tuo codice e testalo due volte. Sarai in grado di correggere i bug che portano alla perdita di dati e nel processo, semplificherai notevolmente l'elaborazione a valle dei dati perché non dovrai preoccuparti di null.


2
Grazie per la risposta. Sono d'accordo che la tua soluzione sia il modo giusto per farlo e tu l'hai formulata in modo conciso. Vincoli al di fuori della mia influenza potrebbero renderlo difficile o impossibile (ad esempio risorse non disponibili per il test o per rendere automaticamente testabile il codice esistente), ma dovrei sicuramente ricontrollare se questa soluzione può funzionare prima di provare altri modi. Nel mio pensiero originale forse ho assunto troppo rapidamente di non poter risolvere il problema alla fonte.
jhyot,

@jhyot Ok. È frustrante quando non puoi fare le cose in modo pulito. Spero che la mia risposta sia utile almeno agli altri che hanno problemi simili ma che sono in grado di attaccare la causa principale invece di ripulire il casino dopo il fatto.
Ripristina Monica il

5

Per quanto riguarda questa frase nella domanda:

Ciò non dovrebbe "teoricamente" accadere, quindi se lo fa punta a dati errati o ad un bug nel codice.

Ho sempre apprezzato questa citazione (per gentile concessione di questo articolo ):

Lo trovo divertente quando i programmatori alle prime armi credono che il loro compito principale sia impedire l'arresto anomalo dei programmi. Immagino che questo spettacolare argomento di fallimento non sarebbe così attraente per un programmatore del genere. I programmatori più esperti si rendono conto che il codice corretto è ottimo, il codice che si arresta in modo anomalo potrebbe utilizzare il miglioramento, ma il codice errato che non si blocca è un incubo orribile.

In sostanza: sembra che tu stia approvando la Legge di Postel , "sii prudente in ciò che invii, sii liberale in ciò che accetti". Sebbene grande in teoria, in pratica questo "principio di robustezza" porta a un software che non è robusto , almeno a lungo termine - e talvolta anche a breve termine. (Confronta l'articolo di Eric Allman The Robustness Principle Reconsidered , che è un trattamento molto approfondito dell'argomento, sebbene principalmente focalizzato sui casi d'uso del protocollo di rete.)

Se si dispone di programmi che sono in modo errato inserimento dei dati nel database, questi programmi sono rotti e hanno bisogno di essere fissato . Il superamento del problema consente solo di continuare a peggiorare; questo è l'equivalente di ingegneria del software che consente a un tossicodipendente di continuare la propria dipendenza.

In termini pragmatici, tuttavia, a volte è necessario consentire al comportamento "rotto" di continuare, almeno temporaneamente, soprattutto come parte di una transizione senza soluzione di continuità da uno stato lassista, rotto a uno stato rigoroso e corretto. In tal caso, si desidera trovare un modo per consentire il corretto inserimento degli inserimenti, ma consentire comunque all'archivio dati "canonico" di essere sempre in uno stato corretto . Esistono vari modi per farlo:

  • Utilizzare un trigger di database per convertire inserti non validi in inserti corretti, ad esempio sostituendo i valori mancanti / null con i valori predefiniti
  • Far inserire i programmi errati in una tabella di database separata che può essere "errata" e disporre di un processo pianificato separato o di un altro meccanismo che sposta i dati corretti da quella tabella nell'archivio dati canonico
  • Utilizzare il filtro sul lato query (ad es. Una vista) per assicurarsi che i dati recuperati dal database siano sempre in uno stato corretto, anche se i dati inattivi non lo sono

Un modo per eludere tutti questi problemi è inserire un livello API che controlli tra i programmi che emettono scritture e il database effettivo.

Sembra che parte del tuo problema sia che non conosci nemmeno tutti i luoghi che generano scritture errate - o che ce ne sono semplicemente troppi da aggiornare. È uno stato spaventoso in cui trovarsi, ma non avrebbe mai dovuto sorgere in primo luogo.

Non appena avrai più di una manciata di sistemi che sono autorizzati a modificare i dati in un archivio di dati di produzione canonico, avrai dei problemi: non c'è modo di mantenere centralmente nulla su quel database. Meglio sarebbe consentire il minor numero possibile di processi per emettere scritture e utilizzare quelli come "gatekeeper" che possono preelaborare i dati prima di inserirli se necessario. Il meccanismo esatto per questo dipende davvero dalla tua architettura specifica.


"Se si dispone di programmi che inseriscono erroneamente i dati nel database, tali programmi vengono interrotti e devono essere corretti." è fantastico anche in teoria, ma la realtà è che aggiungeranno ancora record mentre alcuni comitati continuano a discutere se usare "NA" o "Nessuno".
JeffO,

@JeffO: Nessun comitato dovrebbe discutere se archiviare "NA", "Nessuno", NULL o qualcos'altro nel database. Gli stakeholder non tecnici hanno un interesse in quali dati escono dal database e come vengono utilizzati, ma non nella rappresentazione interna.
Daniel Pryden,

@DanielPryden: Nel mio ultimo lavoro, avevamo un comitato di revisione dell'architettura (con un sottocomitato DBA) che avrebbe esaminato le modifiche tecniche tra domini. Molto tecnico, ma si sono incontrati solo ogni due settimane e se non avessi fornito dettagli sufficienti per loro avrebbero rinviato una decisione fino a quando non l'avresti fatto ... in una riunione successiva. La maggior parte delle modifiche di sistema non banali che non consistono nell'aggiungere funzionalità tramite il nuovo codice richiederebbe normalmente un mese circa.
TMN,

@DanielPryden - Ho partecipato a riunioni con dibattiti dell'alta direzione sulle etichette delle caselle di testo. Si potrebbe sostenere che questo non ha nulla a che fare con il nome che si intende nominare nell'applicazione o nel database, ma lo fa.
JeffO,

In risposta ai commenti su come ottenere ulteriori approvazioni per modifiche di questo tipo: il mio punto sui valori "errati" presuppone che i valori consentiti siano già documentati da qualche parte - ecco perché l'OP afferma che questi valori dovrebbero essere considerati un bug. Se lo schema del database viene specificato per consentire un valore, tale valore non è un bug. Il punto è che se hai dati che non corrispondono al tuo schema, allora qualcosa è rotto: la tua priorità dovrebbe essere quella di far corrispondere i dati e lo schema. A seconda del team, ciò può comportare la modifica dei dati, dello schema o di entrambi.
Daniel Pryden,

2

" Esistono buoni principi di architettura o design per gestire le voci null rare ma possibili? "

Risposta semplice - si.

ETL

Eseguire alcune elaborazioni frontali per garantire che i dati siano di qualità sufficiente per accedere al database. Qualunque cosa nel file di rilascio deve essere riportata indietro e tutti i dati puliti possono essere caricati nel database.

Come qualcuno che è stato sia bracconiere (dev) che game keeper (DBA), so per amara esperienza che terze parti semplicemente non risolveranno i loro problemi di dati a meno che non siano costretti a farlo. Piegarsi costantemente all'indietro e massaggiare i dati attraverso costituisce un precedente pericoloso.

Mart / Repository

In questo scenario, i dati non elaborati vengono trasferiti nel database del repository e quindi una versione disinfettata viene trasferita nel DB mart a cui le applicazioni hanno accesso.

Valori standard

Se è possibile applicare valori predefiniti ragionevoli alle colonne, è possibile che ciò implichi un po 'di lavoro se si tratta di un database esistente.

Fallire presto

È allettante tentare semplicemente di risolvere i problemi relativi ai dati nel gateway per l'applicazione, la suite di report, l'interfaccia ecc. Vi consiglio caldamente di non fare affidamento esclusivamente su questo. Se si collega un altro widget al DB, si potrebbero incontrare nuovamente gli stessi problemi. Risolvi i problemi di qualità dei dati.


+1 Questo è ciò che farei, raccogliere tutti i dati e creare un set di dati valido per l'elaborazione della tua domanda.
Kwebble,

1

Ogni volta che il tuo caso d'uso consente di sostituire NULL in modo sicuro con un buon valore predefinito, puoi fare la conversione nelle SELECTistruzioni Sql usando ISNULLo COALESCE. Quindi invece di

 SELECT MyColumn FROM MyTable

si può scrivere

 SELECT ISNULL(MyColumn,DefaultValueForMyColumn) FROM MyTable

Naturalmente, ciò funzionerà solo quando l'ORM consente di manipolare direttamente le istruzioni selezionate o di fornire modelli modificabili per la generazione. Si dovrebbe assicurarsi che nessun errore "reale" sia mascherato in questo modo, quindi applicarlo solo se la sostituzione con un valore predefinito è esattamente ciò che si desidera in caso di NULL.

Se sei in grado di modificare il database e lo schema e il tuo sistema db lo supporta, puoi considerare di aggiungere una clausola di valore predefinita alle colonne specifiche, come suggerito da @RobbieDee. Tuttavia, ciò richiederà anche di modificare i dati esistenti nel database per rimuovere eventuali valori NULL precedentemente inseriti e in seguito rimuoverà la capacità di distinguere tra dati di importazione corretti e incompleti.

Dalla mia esperienza, so che l'uso di ISNULL può funzionare sorprendentemente bene: in passato dovevo mantenere un'applicazione legacy in cui gli sviluppatori originali avevano dimenticato di aggiungere vincoli NOT NULL a molte colonne e non potevamo facilmente aggiungere tali vincoli in seguito Per alcuni motivi. Ma nel 99% di tutti i casi, 0 come valore predefinito per le colonne numeriche e la stringa vuota come valore predefinito per le colonne di testo era pienamente accettabile.


Mentre funziona, puoi finire per duplicare il codice difensivo per ogni SELECT. Un approccio di gran lunga migliore consiste nel definire un valore predefinito per una colonna quando viene inserito un valore NULL sebbene ciò possa non essere possibile / desiderabile per una serie di motivi.
Robbie Dee,

@RobbieDee: grazie per quell'osservazione, ho modificato la mia risposta di conseguenza. Tuttavia, se questo è "di gran lunga migliore" è discutibile. Quando il codice CRUD si trova in un punto, il codice difensivo duplicato potrebbe non essere un grosso problema. E se non lo è, c'è già una duplicazione del codice in anticipo.
Doc Brown,

Le semplici operazioni CRUD sono ovviamente l'ideale. Ma nel mondo reale, i sistemi hanno spesso viste dell'interfaccia utente complesse, procedure guidate di dati generati dagli utenti, report, ecc. Ma, come hai sottolineato, i valori predefiniti devono essere presenti da zero o almeno richiedere qualche sforzo iniziale di conversione. Quello che hai descritto potrebbe essere preferibile in uno sviluppo brownfield.
Robbie Dee,

Migliore risposta. Le nuove applicazioni di solito aggiungono alcuni nuovi dati che potrebbero essere al di fuori del tuo controllo. I NULL errati di solito provengono dall'importazione di dati legacy in database riprogettati. I vincoli sono disattivati ​​per questo per consentirne il completamento in poche ore anziché diversi giorni. "Il grande fallimento" arriva spesso quando i DBA cercano di riattivare i vincoli. Poiché non è mai stato pianificato, la gestione spesso si oppone alle settimane di lavoro spesso necessarie per correggere i dati errati, quindi rimane. Tutte le app dovrebbero gestire con garbo i NULL inserendo valori predefiniti e segnalando o richiedendo altrimenti i dati mancanti.
DocSalvager

1

Il PO presume una risposta che abbini le regole aziendali ai dettagli tecnici del database.

Ciò non dovrebbe "teoricamente" accadere, quindi se lo fa punta a dati errati o ad un bug nel codice. Gli errori hanno gravità diverse, a seconda del campo nullo; vale a dire che per alcuni campi l'elaborazione dovrebbe essere interrotta e qualcuno notificato, per altri dovrebbe essere consentito il proseguimento dell'elaborazione e avvisare qualcuno.

Queste sono tutte regole aziendali. Alle regole aziendali non interessa nulla di per sé. Per quanto ne sa il database potrebbe avere null, 9999, "BOO!" ... È solo un altro valore. Che, in un RDBMS, null abbia proprietà interessanti e usi unici è controverso.

L'unica cosa che conta è cosa significa "nullità" per gli oggetti di business dati ...

Esistono buoni principi di architettura o di progettazione per gestire le voci null rare ma possibili?

Sì.

  • Metti le regole di business in classe.
  • La traslitterazione dovrebbe trovarsi in un livello di codice appropriato disaccoppiando le business class e l'archivio dati. Se non riesci a inserirlo nel codice ORM almeno non inserirlo nel database.
  • Rendi il database il più stupido possibile, senza regole commerciali qui. Anche cose innocue come il default di un valore ti morderanno . Stato lì.
  • Convalida i dati che vanno e vengono dal database. E ovviamente questo viene fatto nel contesto degli oggetti business.

Generare un'eccezione al momento del recupero dei dati non ha senso.

La domanda è "dovrei archiviare dati" errati "? Dipende:

  • È possibile che vengano utilizzati dati errati - Non salvare mai oggetti non validi o compositi di oggetti. Dati complessi / relazioni commerciali in tutto il luogo. Gli utenti possono svolgere qualsiasi funzione in qualsiasi momento, eventualmente utilizzando tale entità aziendale in numerosi contesti. L'effetto (se presente) di dati errati, al momento del salvataggio, non è noto perché dipende fortemente dall'uso futuro. Non esiste un processo unificato / singolo di tali dati.
  • Impossibile progredire in caso di dati errati : consentire il salvataggio di dati errati. Tuttavia, il passaggio successivo in un processo non può continuare fino a quando tutto è valido. Ad esempio facendo le tasse sul reddito. Quando viene recuperato dal database, il software segnala gli errori e non può essere inviato all'IRS senza controllo di validità.

0

Esistono molti modi per gestire i null, quindi passeremo dal livello del database al livello dell'applicazione.


Livello del database

Puoi vietare i null ; sebbene qui sia poco pratico.

È possibile configurare un valore predefinito per colonna:

  • richiede che la colonna sia assente da insert, quindi non copre l'inserzione nulla esplicita
  • impedisce il rilevamento da righe in cui inserterroneamente ha perso questa colonna

È possibile configurare un trigger , in modo che al momento dell'inserimento i valori mancanti vengano calcolati automaticamente:

  • richiede che siano presenti le informazioni necessarie per eseguire questo calcolo
  • rallenterà il insert

Livello di query

Puoi saltare le righe in cui nullè presente un inconveniente :

  • semplifica la logica principale
  • impedisce di rilevare le "righe errate", quindi sarebbe necessario un altro processo per verificarle
  • richiede che ogni query sia strumentata

È possibile fornire un valore predefinito nella query:

  • semplifica la logica principale
  • impedisce di rilevare le "righe errate", quindi sarebbe necessario un altro processo per verificarle
  • richiede che ogni query sia strumentata

Nota: la strumentazione di ogni query non è necessariamente un problema se si dispone di un modo automatico di generarle.


Livello di applicazione

Puoi pre-controllare la tabella per vietato null:

  • semplifica la logica principale
  • migliora il tempo di insuccesso
  • richiede che il controllo preliminare e la logica dell'applicazione siano coerenti

È possibile interrompere l'elaborazione quando si incontra un proibito null:

  • evita di duplicare la conoscenza di quali colonne possono essere nulle quali no
  • è ancora relativamente semplice (solo un controllo + ritorno / lancio)
  • richiede che il processo sia ripristinabile (se hai già inviato un'e-mail, non vuoi inviarlo due volte o cento volte!)

Puoi saltare la fila quando incontri un proibito null:

  • evita di duplicare la conoscenza di quali colonne possono essere nulle quali no
  • è ancora relativamente semplice (solo un controllo + ritorno / lancio)
  • non richiede la ripresa del processo

Puoi inviare una notifica quando incontri un proibito null, uno alla volta o in gruppo, che è gratuito per gli altri modi presentati sopra. Ciò che conta di più, tuttavia, è "che cosa?", In particolare, se si prevede che la riga venga patchata e necessiti di essere rielaborata, potrebbe essere necessario assicurarsi di avere un modo per distinguere le righe già elaborate dalle righe che necessitano di in fase di rielaborazione.


Data la tua situazione, vorrei gestire la situazione all'applicazione e combinare:

  • interrompere e avvisare
  • salta e notifica

Tenderei solo a saltare, se possibile, per garantire in qualche modo un piccolo progresso, specialmente se l'elaborazione può richiedere del tempo.

Se non è necessario rielaborare le righe ignorate, è sufficiente registrarle semplicemente e un'e-mail inviata alla fine del processo con il numero di righe ignorate sarà una notifica appropriata.

Altrimenti, userei una tabella laterale per le file da correggere (e rielaborare). Questa tabella laterale può essere un semplice riferimento (senza chiave esterna) o una copia completa: quest'ultima, anche se più costosa, è necessaria se non si ha il tempo di occuparsene nullprima di dover ripulire i dati principali.


-1

I null possono essere gestiti nella traduzione o nella mappatura dei tipi di database con i tipi di lingua. Ad esempio in C #, ecco un metodo generico che gestisce null per te per qualsiasi tipo:

public static T Convert<T>(object obj)
        {
            if (obj == DBNull.Value)
            {
                return default(T);
            }

            return (T) obj;
        }

public static T Convert<T>(object obj, T defaultValue)
        {
            if (obj == DBNull.Value)
            {
                T t = defaultValue;
                return t;
            }

            return (T) obj;
        }

Oppure, se si desidera eseguire un'azione ...

 public static T Convert<T>(object obj, T defaultValue)
        {
            if (obj == DBNull.Value)
            {
                //Send an Alert, we might want pass in the name
                //of column or other details as well
                SendNullAlert();
                //Set it to default so we can keep processing
                T t = defaultValue;
                return t;
            }

            return (T) obj;
        }

E quindi nella mappatura, in questo caso a un oggetto di tipo "Esempio", gestiremo null per una delle colonne:

public class SampleMapper : MapperBase<Sample>
    {
        private const string Id = "Id";
        private const string Name = "Name";
        private const string DataValue = "DataValue";
        private const string Created = "Created";

        protected override Sample Map(IDataRecord record)
        {
            return new Sample(
                Utility.Convert<Int64>(record[Id]),
                Utility.Convert<String>(record[Name]),
                Utility.Convert<Int32>(record[DataValue]),
                Utility.Convert<DateTime>(record[Created])
                );
        }
    }

Infine, tutte le classi di mappatura possono essere generate automaticamente in base alla query o alle tabelle SQL coinvolte esaminando i tipi di dati SQL e traducendoli nei tipi di dati specifici della lingua. Questo è ciò che molti ORM fanno automaticamente per te. Si noti che alcuni tipi di database potrebbero non avere una mappatura diretta (colonne geografiche spaziali ecc.) E potrebbe richiedere una gestione speciale.


Se qualcuno vuole pubblicare la versione equivalente di Java sarebbe fantastico ...
Jon Raynor il

Penso che il codice di esempio sia perfettamente comprensibile anche per gli sviluppatori Java. Nella mia situazione ho già un ORM in atto, quindi non è necessario implementarlo. Ma la tua risposta affronta solo i valori predefiniti per i null, mentre nel mio caso in realtà il caso molto più importante è il rilevamento di un null e l'attivazione di un'azione (ad esempio informare un amministratore sui dati errati).
jhyot,

Ahhh, aggiornerò la mia risposta basandomi su questo.
Jon Raynor,

Il tuo codice modificato ora ha un'azione predefinita per qualsiasi valore nullo (cioè è completamente generico). È molto simile alla mia seconda opzione nella domanda originale, vale a dire basta lanciare su null e prenderlo da qualche parte. Ma, come indicato, devo differenziare le azioni in base al valore mancante.
jhyot,
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.