Diseños y prácticas para proteger contra entradas nulas erróneas de la base de datos

9

Una parte de mi programa obtiene datos de muchas tablas y columnas de mi base de datos para su procesamiento. Algunas de las columnas pueden ser null, pero en el contexto de procesamiento actual es un error.

Esto "teóricamente" no debería suceder, por lo que si lo hace, apunta a datos incorrectos o un error en el código. Los errores tienen diferentes severidades, dependiendo de qué campo es null; es decir, para algunos campos, el procesamiento debe detenerse y alguien debe ser notificado; para otros, se debe permitir que el procesamiento continúe y simplemente notificar a alguien.

¿Hay alguna buena arquitectura o principios de diseño para manejar las nullentradas raras pero posibles ?

Las soluciones deberían ser posibles de implementar con Java, pero no utilicé la etiqueta porque creo que el problema es algo agnóstico al lenguaje.


Algunos pensamientos que tuve yo mismo:

Usando NOT NULL

Lo más fácil sería usar una restricción NOT NULL en la base de datos.

Pero, ¿qué sucede si la inserción original de los datos es más importante que este paso de procesamiento posterior? Por lo tanto, en caso de que el inserto pusiera un elemento nullen la tabla (ya sea por errores o incluso por alguna razón válida), no quisiera que el inserto falle. Digamos que muchas más partes del programa dependen de los datos insertados, pero no de esta columna en particular. Por lo tanto, prefiero arriesgarme al error en el paso de procesamiento actual en lugar del paso de inserción. Es por eso que no quiero usar una restricción NOT NULL.

Ingenuamente dependiendo de NullPointerException

Podría usar los datos como si esperara que siempre estuvieran allí (y ese debería ser realmente el caso), y capturar los NPE resultantes en un nivel apropiado (por ejemplo, para que el procesamiento de la entrada actual se detenga pero no todo el progreso del procesamiento) ) Este es el principio de "falla rápida" y a menudo lo prefiero. Si es un error, al menos obtengo un NPE registrado.

Pero luego pierdo la capacidad de diferenciar entre varios tipos de datos faltantes. Por ejemplo, para algunos datos faltantes, podría omitirlos, pero para otros, el procesamiento debería detenerse y notificar a un administrador.

Comprobando nullantes de cada acceso y lanzando excepciones personalizadas

Las excepciones personalizadas me permitirían decidir la acción correcta en función de la excepción, por lo que este parece ser el camino a seguir.

Pero, ¿qué pasa si me olvido de revisarlo en alguna parte? Además, abarroto mi código con verificaciones nulas que nunca o raramente se esperan (y definitivamente no forman parte del flujo de lógica de negocios).

Si elijo seguir este camino, ¿qué patrones son los más adecuados para el enfoque?


Cualquier pensamiento y comentario sobre mis enfoques son bienvenidos. También mejores soluciones de cualquier tipo (patrones, principios, mejor arquitectura de mi código o modelos, etc.).

Editar:

Hay otra restricción, ya que estoy usando un ORM para hacer el mapeo de DB a objeto de persistencia, por lo que hacer comprobaciones nulas en ese nivel no funcionaría (ya que los mismos objetos se usan en partes donde el nulo no hace ningún daño) . Agregué esto porque las respuestas proporcionadas hasta ahora mencionaron esta opción.

jhyot
fuente
55
"Algunas de las columnas pueden ser nulas, pero en el contexto de procesamiento actual eso es un error ... en caso de que el inserto pusiera un nulo en la tabla, no quisiera que el inserto fallara". Esos dos requisitos son contradictorio. Es imposible encontrar una solución hasta que relajes una de las dos condiciones.
Kilian Foth
@KilianFoth Bueno, mi relajación es que el error en el contexto del "procesamiento actual" es menos severo que cuando se inserta. Así que acepto los errores de procesamiento raros, pero quiero tener un buen diseño robusto para manejarlos. Es por eso que NOT NULL, que de otra manera sería una buena solución, no es posible aquí.
jhyot
1
Si acepta tantos errores, los creadores de esos errores nunca los corregirán. Si sus declaraciones de inserción desordenadas tienen éxito, ¿qué incentivo tienen para arreglar las cosas? ¿Considera que la robustez no falla sino que acepta datos incorrectos?
Tulains Córdova
@ user61852 No acepto explícitamente los errores, pero quiero manejarlos con gracia. La ingestión de punteros nulos está fuera de discusión. Además, ¿qué sucede si mi parte es realmente objetivamente (según la definición de la empresa) menos importante que muchas otras partes que requieren que la inserción tenga éxito pero no requieren que se establezca este campo en particular? Las inserciones se originan no en una entrada de usuario donde podría obligarlos a agregar el valor, sino en otro código donde la omisión es más probable un error (pero no lo suficientemente importante como para romper la inserción).
jhyot
1
Marcarlos como NO NULL en la base de datos sería la mejor solución, si una columna es anulable, entonces el código deberá manejar el caso cuando lo sea, incluso si no se espera porque el mecanismo de almacenamiento lo permite.
Jon Raynor

Respuestas:

9

Pondría las verificaciones nulas en su código de mapeo, donde construye su objeto a partir del conjunto de resultados. Eso coloca la verificación en un lugar y no permitirá que su código llegue a la mitad del procesamiento de un registro antes de detectar un error. Dependiendo de cómo funcione el flujo de su aplicación, es posible que desee realizar la asignación de todos los resultados como un paso de preprocesamiento en lugar de asignar y procesar cada registro de uno en uno.

Si está utilizando un ORM, deberá realizar todas las comprobaciones nulas antes de procesar cada registro. Recomendaría un recordIsValid(recordData)método de tipo, de esa manera puede (nuevamente) mantener toda la lógica de verificación nula y otra lógica de validación en un solo lugar. Definitivamente no mezclaría los cheques nulos con el resto de su lógica de procesamiento.

TMN
fuente
Gracias, esa es una buena idea! De hecho, estoy usando un ORM, por lo que las comprobaciones en ese nivel no funcionarán. Pero también tengo algo de mapeo a objetos de dominio real de los objetos de persistencia. Comprobaré si sería posible hacer el mapeo y validar en un paso de preprocesamiento.
jhyot
Y si cambias tu ORM, ¿entonces qué? Es mejor defender esto en la fuente (ver la respuesta del Doc Brown).
Robbie Dee
@RobbieDee: No debería importar. Si tiene que reescribir el código de mapeo, entonces las verificaciones nulas están allí y las modifica como parte de la reescritura, o tiene un método separado que realiza las verificaciones nulas en sus objetos comerciales, por lo que no es necesario reescribir. Y como lo implica el Doc Brown, a veces es importante notar que faltan datos en lugar de pasar por alto ese hecho con un valor predeterminado.
TMN
Eso debería suceder más arriba en el flujo de ETL. Todavía corre el riesgo de duplicar el esfuerzo de esta manera.
Robbie Dee
6

Parece que insertar un valor nulo es un error, pero tiene miedo de aplicar este error en la inserción porque no desea perder datos. Sin embargo, si un campo no debería ser nulo pero sí, está perdiendo datos . Por lo tanto, la mejor solución es asegurarse de que los campos nulos no se guarden erróneamente en primer lugar.

Con este fin, haga cumplir que los datos sean correctos en el único repositorio autorizado y permanente para esos datos, la base de datos. Hágalo agregando restricciones no nulas. Entonces, su código puede fallar, pero estas fallas le notifican de inmediato los errores, lo que le permite corregir los problemas que ya están causando la pérdida de datos. Ahora que puede identificar fácilmente errores, pruebe su código y pruébelo dos veces. Podrá corregir errores que conducen a la pérdida de datos y, en el proceso, simplificar en gran medida el procesamiento posterior de los datos porque no tendrá que preocuparse por los nulos.

Reinstalar a Mónica
fuente
2
Gracias por la respuesta. Estoy de acuerdo en que su solución es la forma correcta de hacerlo, y lo ha expresado de manera concisa. Las restricciones fuera de mi influencia pueden hacer que sea difícil o imposible (por ejemplo, recursos no disponibles para probar o hacer que el código existente sea automáticamente comprobable), pero definitivamente debería verificar si esta solución puede funcionar antes de probar otras formas. En mi pensamiento original, tal vez asumí demasiado rápido que no puedo solucionar el problema en la fuente.
jhyot
@jhyot De acuerdo. Es frustrante cuando no puedes hacer las cosas de manera limpia. Espero que mi respuesta sea al menos útil para otras personas que tienen problemas similares pero que pueden atacar la causa raíz en lugar de limpiar el desorden después del hecho.
Restablece a Mónica el
5

Con respecto a esta oración en la pregunta:

Esto "teóricamente" no debería suceder, por lo que si lo hace, apunta a datos incorrectos o un error en el código.

Siempre he apreciado esta cita (cortesía de este artículo ):

Me resulta divertido cuando los programadores novatos creen que su trabajo principal es evitar que los programas se bloqueen. Me imagino que este espectacular argumento de fracaso no sería tan atractivo para un programador así. Los programadores más experimentados se dan cuenta de que el código correcto es excelente, el código que falla podría mejorar, pero el código incorrecto que no falla es una pesadilla horrible.

Básicamente: parece que estás respaldando la Ley de Postel , "sé conservador en lo que envías, sé liberal en lo que aceptas". Si bien es excelente en teoría, en la práctica este "principio de robustez" conduce a un software que no es robusto , al menos a largo plazo, y a veces también a corto plazo. (Compárese el artículo de Eric Allman, El principio de robustez reconsiderado , que es un tratamiento muy completo del tema, aunque se centra principalmente en los casos de uso del protocolo de red).

Si tiene programas que están insertando datos incorrectamente en su base de datos, esos programas están rotos y deben repararse . Empapelar el problema solo le permite seguir empeorando; Este es el equivalente en ingeniería de software de permitir que un adicto continúe su adicción.

Sin embargo, en términos pragmáticos, a veces es necesario permitir que continúe el comportamiento "roto", al menos temporalmente, especialmente como parte de una transición fluida de un estado laxo y roto a un estado estricto y correcto. En ese caso, desea encontrar una manera de permitir que las inserciones incorrectas tengan éxito, pero aún así permitir que el almacén de datos "canónicos" siempre esté en un estado correcto . Hay varias maneras de hacer esto:

  • Utilice un desencadenador de base de datos para convertir inserciones mal formadas en inserciones correctas, por ejemplo, reemplazando los valores faltantes / nulos con valores predeterminados
  • Haga que los programas incorrectos se inserten en una tabla de base de datos separada que puede ser "incorrecta", y tenga un proceso programado separado u otro mecanismo que mueva los datos corregidos de esa tabla al almacén de datos canónico
  • Utilice el filtrado del lado de la consulta (por ejemplo, una vista) para asegurarse de que los datos recuperados de la base de datos estén siempre en un estado correcto, incluso si los datos en reposo no están

Una forma de evitar todos estos problemas es insertar una capa de API que controle entre los programas que emiten escrituras y la base de datos real.

Parece que parte de su problema es que ni siquiera conoce todos los lugares que generan escrituras incorrectas, o que simplemente hay demasiados para que pueda actualizar. Es un estado aterrador, pero nunca se debería haber permitido que surgiera en primer lugar.

Tan pronto como obtenga más de un puñado de sistemas que tienen permiso para modificar datos en un almacén de datos de producción canónico, se encontrará en problemas: no hay forma de mantener centralmente nada sobre esa base de datos. Mejor sería permitir la menor cantidad posible de procesos para emitir escrituras, y usarlas como "guardianes" que puedan preprocesar los datos antes de insertarlos según sea necesario. El mecanismo exacto para esto realmente depende de su arquitectura específica.

Daniel Pryden
fuente
"Si tiene programas que están insertando datos incorrectamente en su base de datos, esos programas están rotos y deben repararse". eso también es genial en teoría, pero la realidad es que seguirán agregando registros mientras algún comité continúa debatiendo si usar "NA" o "Ninguno".
JeffO
@JeffO: Ningún comité debería debatir si almacenar "NA", "Ninguno", NULL u otra cosa en la base de datos. Las partes interesadas no técnicas tienen interés en qué datos salen de la base de datos y cómo se usan, pero no en la representación interna.
Daniel Pryden
@DanielPryden: En mi último trabajo, tuvimos una Junta de Revisión de Arquitectura (con un subcomité de DBA) que revisaría los cambios técnicos entre dominios. Muy técnico, pero solo se reunían cada dos semanas y si no proporcionabas suficientes detalles para ellos, aplazarían una decisión hasta que lo hicieras ... en una reunión posterior. La mayoría de los cambios no triviales en el sistema que no consistían en agregar funcionalidad a través de un nuevo código llevarían habitualmente un mes más o menos.
TMN
@DanielPryden: me he sentado en reuniones con la alta gerencia debatiendo sobre etiquetas de cuadros de texto. Podría argumentar que esto no tiene nada que ver con lo que va a nombrar en la aplicación o la base de datos, pero lo hace.
JeffO
En respuesta a los comentarios sobre la obtención de aprobaciones adicionales para cambios de este tipo: mi punto sobre los valores "incorrectos" presupone que los valores permitidos ya están documentados en alguna parte, es por eso que el OP dice que estos valores deben considerarse un error. Si se especifica el esquema de la base de datos para permitir un valor, ese valor no es un error. El punto es que si tiene datos que no coinciden con su esquema, entonces algo está roto: su prioridad debe ser hacer que los datos y el esquema coincidan. Dependiendo del equipo, eso puede implicar cambiar los datos, el esquema o ambos.
Daniel Pryden
2

" ¿Hay alguna buena arquitectura o principios de diseño para manejar las entradas nulas raras pero posibles? "

Respuesta simple: sí.

ETL

Realice un procesamiento inicial para garantizar que los datos sean de calidad suficiente para ingresar a la base de datos. Cualquier cosa en el archivo desplegable debe ser informada y cualquier dato limpio puede cargarse en la base de datos.

Como alguien que ha sido tanto cazador furtivo (dev) como guardián del juego (DBA), sé por amarga experiencia que los terceros simplemente no resolverán sus problemas de datos a menos que se vean obligados a hacerlo. Doblar constantemente hacia atrás y masajear los datos establece un precedente peligroso.

Mart / Repository

En este escenario, los datos sin procesar se introducen en la base de datos del repositorio y luego se envía una versión desinfectada a la base de datos de mart a la que las aplicaciones tienen acceso.

Valores predeterminados

Si puede aplicar valores predeterminados razonables a las columnas, debería hacerlo, aunque esto puede implicar algo de trabajo si se trata de una base de datos existente.

Fallar temprano

Es tentador simplemente abordar los problemas de datos en la puerta de enlace a la aplicación, el conjunto de informes, la interfaz, etc. Le recomiendo encarecidamente que no confíe únicamente en esto. Si conecta algún otro widget a la base de datos, posiblemente volverá a enfrentar los mismos problemas. Abordar los problemas de calidad de los datos.

Robbie Dee
fuente
+1 Esto es lo que haría, recopilar todos los datos y crear un conjunto de datos válido para que su aplicación lo procese.
Kwebble
1

Siempre que su caso de uso permita reemplazar NULL de forma segura por un buen valor predeterminado, puede hacer la conversión en las SELECTdeclaraciones SQL usando ISNULLo COALESCE. Entonces en lugar de

 SELECT MyColumn FROM MyTable

uno puede escribir

 SELECT ISNULL(MyColumn,DefaultValueForMyColumn) FROM MyTable

Por supuesto, eso solo funcionará cuando el ORM permita manipular las sentencias select directamente o proporcionar plantillas modificables para la generación. Uno debe asegurarse de que no haya errores "reales" enmascarados de esta manera, así que aplíquelo solo si el reemplazo por un valor predeterminado es exactamente lo que desea en caso de NULL.

Si puede cambiar la base de datos y el esquema, y ​​su sistema db lo admite, puede considerar agregar una cláusula de valor predeterminado a las columnas específicas, como lo sugiere @RobbieDee. Sin embargo, esto también requerirá modificar los datos existentes en la base de datos para eliminar cualquier valor NULL insertado previamente, y eliminará la capacidad de distinguir entre datos de importación correctos e incompletos después.

Según mi propia experiencia, sé que usar ISNULL puede funcionar sorprendentemente bien: en el pasado tuve que mantener una aplicación heredada donde los desarrolladores originales se habían olvidado de agregar restricciones NOT NULL a muchas columnas, y no pudimos agregar fácilmente esas restricciones más adelante por algunas razones. Pero en el 99% de todos los casos, 0 como valor predeterminado para las columnas de números y la cadena vacía como valor predeterminado para las columnas de texto era totalmente aceptable.

Doc Brown
fuente
Si bien esto funciona, puede terminar teniendo que duplicar el código defensivo para cada SELECT. Un enfoque mucho mejor es definir un valor predeterminado para una columna cuando se inserta un NULL, aunque esto puede no ser posible / deseable por una variedad de razones.
Robbie Dee
@RobbieDee: gracias por ese comentario, cambié mi respuesta en consecuencia. Sin embargo, si esto es "mucho mejor" es discutible. Cuando el código CRUD está en un lugar, duplicar el código defensivo puede no ser un gran problema. Y si no es así, ya hay alguna duplicación de código de antemano.
Doc Brown el
Las operaciones CRUD simples son, por supuesto, el ideal. Pero en el mundo real, los sistemas a menudo tienen vistas de interfaz de usuario complejas, asistentes de datos generados por el usuario, informes, etc. Pero, como ha señalado, los valores predeterminados deben estar allí desde cero o al menos requieren un esfuerzo de conversión inicial. Lo que ha descrito podría ser preferible en un desarrollo brownfield.
Robbie Dee
La mejor respuesta. Las nuevas aplicaciones generalmente agregan algunos datos nuevos que pueden estar fuera de su control. Los NULL erróneos generalmente provienen de la importación de datos heredados en bases de datos rediseñadas. Las restricciones están desactivadas para permitir que se complete en unas pocas horas en lugar de varios días. "El gran fracaso" a menudo se produce cuando los DBA intentan volver a habilitar las restricciones. Como nunca se planificó, la administración a menudo se resiste a las semanas de trabajo que a menudo se requieren para corregir los datos incorrectos, por lo que permanece. Todas las aplicaciones deben manejar con gracia los NULL insertando valores predeterminados e informando o solicitando los datos faltantes de lo contrario.
DocSalvager
1

El OP supone una respuesta que combina las reglas de negocio con los detalles técnicos de la base de datos.

Esto "teóricamente" no debería suceder, por lo que si lo hace, apunta a datos incorrectos o un error en el código. Los errores tienen diferentes severidades, dependiendo de qué campo es nulo; es decir, para algunos campos, el procesamiento debe detenerse y alguien debe ser notificado; para otros, se debe permitir que el procesamiento continúe y simplemente notificar a alguien.

Estas son todas las reglas de negocios. Las reglas comerciales no se preocupan por nulo per-se. Por lo que sabe, la base de datos podría tener un valor nulo, 9999, "BOO!" ... Es solo otro valor. Que, en un RDBMS, nulo tiene propiedades interesantes y usos únicos es discutible.

Lo único que importa es lo que significa "nulidad" para los objetos comerciales dados ...

¿Hay alguna buena arquitectura o principios de diseño para manejar las entradas nulas raras pero posibles?

Si.

  • Ponga reglas de negocios en clases.
  • La transliteración debe estar en una capa de código apropiada que desacople las clases de negocios y el almacén de datos. Si no puede ponerlo en el código ORM, al menos no lo ponga en la base de datos.
  • Haga la base de datos lo más tonta posible, no hay reglas de negocios aquí. Incluso cosas inocuas como el incumplimiento de un valor lo morderán . Estado allí.
  • Valide los datos que van y vienen de la base de datos. Y, por supuesto, esto se hace en el contexto de los objetos comerciales.

Lanzar una excepción en la recuperación de datos no tiene sentido.

La pregunta es "¿debo almacenar datos" malos "? Depende:

  • Se pueden utilizar datos incorrectos : nunca guarde objetos no válidos o compuestos de objetos. Datos complejos / relaciones comerciales en todo el lugar. Los usuarios pueden realizar cualquier función en cualquier momento, posiblemente utilizando esa entidad comercial en varios contextos. El efecto (si lo hay) de los datos incorrectos, en el momento en que se guardan, no se conoce porque depende en gran medida del uso futuro. No hay un proceso unificado / único de esos datos.
  • No puede progresar si hay datos incorrectos : permite guardar datos incorrectos. Sin embargo, el siguiente paso en un proceso no puede continuar hasta que todo sea válido. Por ejemplo, hacer los impuestos sobre la renta. Cuando se recupera de la base de datos, el software señala los errores y no se puede enviar al IRS sin una verificación de validez.
radarbob
fuente
0

Hay muchas formas de manejar nulos, por lo que pasaremos de la capa de base de datos a la capa de aplicación.


Capa de base de datos

Puedes prohibir los nulos ; aunque aquí no es práctico.

Puede configurar un valor predeterminado por columna:

  • requiere que la columna esté ausente de insert, por lo que no cubre la inserción nula explícita
  • evita la detección de filas donde inserterróneamente perdió esta columna

Puede configurar un activador , de modo que, al insertarlos, los valores faltantes se calculen automáticamente:

  • requiere que la información necesaria para realizar este cálculo esté presente
  • ralentizará el insert

Capa de consulta

Puede omitir filas donde haya un inconveniente null:

  • simplifica la lógica principal
  • evita detectar las "filas incorrectas", por lo que sería necesario otro proceso para verificarlas
  • requiere que cada consulta sea instrumentada

Puede proporcionar un valor predeterminado en la consulta:

  • simplifica la lógica principal
  • evita detectar las "filas incorrectas", por lo que sería necesario otro proceso para verificarlas
  • requiere que cada consulta sea instrumentada

Nota: instrumentar cada consulta no es necesariamente un problema si tiene alguna forma automatizada de generarlas.


Capa de aplicación

Puede verificar previamente la tabla para lo prohibido null:

  • simplifica la lógica principal
  • mejora el tiempo de falla
  • requiere mantener la verificación previa y la lógica de aplicación consistentes

Puede interrumpir el procesamiento cuando encuentre un prohibido null:

  • evita duplicar el conocimiento de qué columnas pueden ser nully cuáles no
  • sigue siendo relativamente simple (solo un cheque + retorno / lanzamiento)
  • requiere que su proceso sea reanudable (si ya envió un correo electrónico, ¡no quiera enviarlo dos o cien veces!)

Puede omitir la fila cuando encuentre un prohibido null:

  • evita duplicar el conocimiento de qué columnas pueden ser nully cuáles no
  • sigue siendo relativamente simple (solo un cheque + retorno / lanzamiento)
  • no requiere que su proceso sea reanudable

Puede enviar una notificación cuando encuentre un prohibido null, ya sea uno a la vez o por lotes, que es complementario a las otras formas presentadas anteriormente. Sin embargo, lo que más importa es "¿entonces qué?", ​​Especialmente si espera que la fila sea parcheada y necesita ser reprocesada, es posible que deba asegurarse de que tiene alguna forma de distinguir las filas ya procesadas de las filas que necesitan siendo reprocesado.


Dada su situación, manejaría la situación en la aplicación y combinaría:

  • interrumpir y notificar
  • omitir y notificar

Si fuera posible, tendería a omitir para garantizar de alguna manera un mínimo de progreso, especialmente si el procesamiento puede llevar tiempo.

Si no necesita volver a procesar las filas omitidas, simplemente registrarlas debería ser suficiente y un correo electrónico enviado al final del proceso con el número de filas omitidas será una notificación adecuada.

De lo contrario, usaría una tabla lateral para que las filas se arreglen (y se vuelvan a procesar). Esta tabla lateral puede ser una referencia simple (sin clave foránea) o una copia completa: esta última, incluso si es más costosa, es necesaria si no tiene tiempo para abordar la información nullantes de tener que limpiar los datos principales.

Matthieu M.
fuente
-1

Los nulos se pueden manejar en la traducción o asignación de tipos de bases de datos a tipos de idiomas. Por ejemplo, en C #, aquí hay un método genérico que maneja nulo para usted para cualquier 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;
        }

O, si quieres realizar una acción ...

 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;
        }

Y luego, en la asignación, en este caso a un objeto de tipo "Muestra", manejaremos nulo para cualquiera de las columnas:

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])
                );
        }
    }

Finalmente, todas las clases de mapeo se pueden generar automáticamente en función de la consulta SQL o las tablas involucradas al observar los tipos de datos SQL y traducirlos a los tipos de datos específicos del idioma. Esto es lo que muchos ORM hacen por usted automáticamente. Tenga en cuenta que algunos tipos de bases de datos pueden no tener una asignación directa (columnas geoespaciales, etc.) y pueden necesitar un manejo especial.

Jon Raynor
fuente
Si alguien quiere publicar la versión equivalente de Java que sería genial ...
Jon Raynor
Creo que el código de ejemplo es perfectamente comprensible también para los desarrolladores de Java. En mi situación, ya tengo un ORM, así que no necesito implementar uno. Pero su respuesta solo aborda los valores predeterminados para nulos, mientras que en mi caso, el caso mucho más importante es detectar un nulo y desencadenar una acción (por ejemplo, informar a un administrador sobre los datos erróneos).
jhyot
Ahhh, actualizaré mi respuesta en base a esto.
Jon Raynor
Su código editado ahora tiene una acción predeterminada para cualquier valor nulo (es decir, es completamente genérico). Eso es muy similar a mi segunda opción en la pregunta original, es decir, simplemente arroje nulo y atrape en algún lugar. Pero como se indicó allí, necesito diferenciar las acciones según el valor que falta.
jhyot