2011-05-17 7 views
8

Durante un tiempo he estado pensando acerca de cómo lidiar con los objetos que se asignan identificadores de la base de datos.Tratar con identificadores de entidad de diseño de objetos

Un objeto típico que representa una entidad tabla puede verse como:

public class Test 
{ 
    public int Id { get; private set; } 
    public string Something { get; set; } 
} 

Supongamos que nos gustaría utilizar este objeto para insertar, recuperar y actualizar objetos en la base de datos. En cuanto a la recuperación y actualización no tenemos problemas, ya que el campo Id siempre tiene un valor.

Sin embargo, si queremos insertar un nuevo objeto del tipo de prueba en la base de datos, el campo ID se todavía tiene que tener un valor. Podríamos simplemente usar "0", ya que es poco probable que se use como clave de base de datos, pero realmente este no es un buen diseño.

Del mismo modo, si invertimos la situación y hacer que la propiedad Id anulable, podríamos utilizar null para los objetos que aún no se les ha asignado un identificador de la base de datos. Sin embargo, ahora es posible que un objeto recuperado de la base de datos no tenga un identificador (como lo permite el diseño de clase, pero no el diseño de la base de datos)

¿Alguna buena idea sobre cómo hacer un buen diseño para este problema?

+0

que no es posible conseguir un objeto sin un identificador, si se recupera de la base de datos .. y cuando se inserta, se obtendrá un id de inmediato (a menos que tenga alguna base de datos reaaally extraña) – xs0

+0

@ xs0 Obviamente . Sin embargo, mirando estrictamente la definición del tipo de objeto, esto es posible. – DEHAAS

+0

Bueno, dices lo contrario en tu pregunta ... Pero de todos modos, ¿qué quieres hacer con estos objetos? A menos que explique qué operaciones se realizarán con ellos, no está claro cuál es el problema. – xs0

Respuesta

1

tanto, usted tiene una clase que contiene el identificador de tabla de base de datos como un campo, por lo que en caso de recuperación/eliminación y updation identificador de su entidad está alineado con el identificador del registro de la base. En caso de inserción, puede recuperar el valor de identificación del registro recién insertado y actualizar su entidad con ese valor. Por lo tanto, podría tener procedimientos de almacenamiento separados para la inserción/actualización/recuperación y eliminación. La inserción SP podría devolverle la identificación del registro recién insertado como out parameter. Espero que responda tu pregunta.

+0

Estoy de acuerdo con la afirmación de Abdul de que es responsabilidad del DB determinar nuevos valores de ID y establecer los valores por defecto que sean apropiados para nuevos registros. Debe solicitar una nueva fila desde la base de datos y luego permitir que el usuario modifique la nueva fila, si así lo desea. – Beth

+0

Ciertamente, al objeto se le asignaría una identificación después de ser insertado en la base de datos y esta identificación podría establecerse en el objeto que se está insertando. Sin embargo, todavía veo un problema que representa el objeto antes de asignar un identificador. – DEHAAS

+0

¿Cuál es el problema que ves? –

3

Si tratas id como una manera de identificar/otorgar singularidad de oposición en su aplicación, esto debe ser manejado por la base de datos (a menos por supuesto, usted tiene otras maneras de asignar identificadores a objetos).

Si no es (como en, es propiedad del objeto impulsado por las necesidades del negocio) - si 0 es válido/buen valor de diseño o no depende de esas necesidades comerciales puramente. ¿Es 0 un valor válido de decir, el punto de vista del usuario final?

Siempre puede ajustar sus propiedades de objeto en una clase separada, si siente que tener objetos sin ids en su aplicación es problemático. Utilizará dicha clase esencialmente solo para llevar los parámetros para el objeto creado todavía no (el proceso de creación se finaliza con la inserción de la base de datos). Una vez que el objeto se inserta, se asigna la identificación y todo eso, puedes trabajar con tu entidad habitual. ¿Su usuario va a "Oh, chasquido! ¿Qué es eso?" o "Ok ... sé qué hacer". una vez que se haya acercado al id = 0?

Editar

Esta pregunta (o más bien mi respuesta acerca de envolver parámetros) me recordó un hecho que una vez me sorprendió. Cuando nace un niño, no existe en el sistema hasta que sus padres lo registran oficialmente y obtiene con el número de identificación personal asignado. Entonces, técnicamente, sin id - el niño no existe (al menos desde el punto de vista del sistema), aunque todos saben que ella nació y esas cosas.Es lo mismo con la base de datos/su aplicación: el objeto sin id (uno que la base de datos no puede identificar) no existe; es solo un conjunto de parámetros. Bit bizzare, pero espero que mi punto sea claro :)

3

No hay nada de malo en diseñar una clase para que una ID de 0 indique que la entidad aún no ha sido serializada. He construido sistemas en el pasado que utilizaron con éxito este enfoque. Solo asegúrate de que estas semánticas estén bien definidas en tu API, y que este significado se respete en todo el código.

Una trampa a tener en cuenta es usar la ID para definir una relación de igualdad (como para generar códigos hash para un diccionario). Esto solo se debe hacer para identificadores que no sean cero. Para probar la igualdad con dos ID de cero, se puede usar la igualdad de referencia.

Sin embargo, dado que las entidades no sujetas pueden tener su ID de cambio en algún momento en el futuro, es muy importante que tales objetos nunca se almacenen en un diccionario. O, como mínimo, dichos elementos deben eliminarse de todos los diccionarios antes de guardarlos y luego restaurarlos utilizando la nueva ID.

Con esa única reserva, este diseño debería funcionar bien.

public class Test : IEquatable<Test> 
{ 
    /// <summary> 
    /// The unique identifier for this Test entity, or zero if this 
    /// Test entity has not yet been serialized to the database. 
    /// </summary> 
    public int Id { get; private set; } 

    public string Something { get; set; } 

    public override bool Equals(object obj) 
    { 
     return Equals(obj as Test); 
    } 

    public bool Equals(Test other) 
    { 
     if (other == null) 
      return false; 
     // Distinct entities may exist with the Id value of zero. 
     if (Id == 0) 
      return object.ReferenceEquals(this, other); 
     return Id == other.Id; 
    } 

    /// <summary> 
    /// Gets a hash code for this Test entity. Warning: an instance with 
    /// an Id of zero will change its identity when saved to the DB. Use with care. 
    /// </summary> 
    /// <returns>The hash code.</returns> 
    public override int GetHashCode() 
    { 
     return Id; 
    } 
} 
+0

Me doy cuenta de que una identificación de 0 que indica que un objeto no tiene una identificación es ciertamente una solución de trabajo válida; Me preguntaba si sería factible hacer algo mejor. Creo que siempre es mejor no permitir datos "incorrectos" y documentar su salida de ellos, en lugar de no permitir que sean posibles. – DEHAAS

+0

@DEHAAS - Sí, esa fue una de las opciones en su pregunta original. Solo decía que, en mi opinión, está bien. No veo ninguna distinción entre definir 0 como no guardado vs. definir nulo de esa manera, excepto que el primero es un poco menos problemático que el segundo. En mi opinión, documentar e implementar adecuadamente un valor especial es una buena solución. –

+0

@DEHAAS - Piense de esta manera: en un 'doble', el primer bit se interpreta para indicar si el valor numérico es positivo o negativo. Sin embargo, es un poco como cualquier otro, y puede interpretarse de otras formas en otros contextos. Definir ciertas combinaciones de bits como que significan una cosa en oposición a otra cosa es una parte básica de la programación, y no indica un mal diseño. –

Cuestiones relacionadas