2009-05-13 9 views
16

¿Por qué se considera correcto tener un campo Id en las entidades de dominio? He visto varias soluciones que proporcionan una clase base con GetHashCode/Equals basado en Id y Id.DDD: claves principales (Id) y ORM (por ejemplo, NHibernate)

Mi comprensión del modelo de dominio es que debe contener solo cosas relacionadas con el dominio. Si bien en casos excepcionales (órdenes rastreables) los Ids son significativos, la mayoría de las veces no proporcionan nada, excepto una forma simple de referenciar objetos en DB/on UI.

No veo los beneficios Equals/GetHashCode tampoco, ya que la implementación de Identity Map debería garantizar que la igualdad de referencia sea igualdad de id.

Extrañamente, no puedo encontrar fácilmente lo que otras personas piensan sobre este tema, así que lo estoy preguntando aquí. ¿Cuál es la opinión general sobre el uso de Ids no relacionados con el dominio en las entidades de dominio? ¿Y hay algún problema con NHibernate si no agrego Ids a las entidades de mi dominio?

ACTUALIZACIÓN:

Gracias por las respuestas.

Varios de ellos sugieren que tener Id es la única forma de que el ORM haga una actualización de base de datos. No creo que este sea el caso. ORM ya realiza un seguimiento de todas las entidades cargadas desde el DB, por lo que debería ser capaz de obtener un ID internamente cuando lo necesite.

ACTUALIZACIÓN 2:

respuesta a la Justicia y puntos similares: ¿Qué pasa si tenemos una aplicación web y necesidad una manera de hacer referencia a la entidad entre las sesiones? Me gusta edit/resource/id?

Bueno, veo esto como una necesidad específica de la interfaz de usuario restringida/entorno, no es un modelo de dominio necesario. Tener un servicio de aplicaciones o un repositorio con el método GetIdentitity (coherente con el método Load (identity)) parece ser suficiente para este escenario.

+1

¿Cómo implementaría GetIdentity si no tiene un identificador? Obtendría el objeto del cliente y tendría que buscar la identidad. ¿Cómo lo encontrarías? El contenido del objeto podría haber sido cambiado en el cliente. No lo encontrarías más. También respondí tus comentarios a mi respuesta. –

+0

No me refiero al hecho cuando recibo un objeto del cliente. En este caso, probablemente obtenga algún DTO que tenga un Id (y esto es relevante incluso si no tengo un DB y almaceno todo en la memoria, en este caso Id en DTO puede ser una clave en alguna Hashtable interna). Pero antes de enviar el objeto al cliente, puedo obtener un Id y agregarlo al DTO que estoy enviando. O simplemente envíe un Id en algunos casos. –

+0

¡Acabo de encontrar en la documentación de NH que NH no necesita una propiedad de identificación! Ver mi respuesta, agregué una sección. –

Respuesta

4

yo sólo puedo hablar de NHibernate. Allí necesita un campo para la clave principal, depende de usted si toma datos comerciales (no recomendados) o una clave sustituta sin significado comercial.

escenarios típicos son:

  • incremento automático valor generado por la base de datos
  • GUID generado por NHibernate
  • GUID generada por la lógica de negocio

No es una gran ventaja tener una identificación única. Cuando pasa el objeto, por ejemplo al cliente y de vuelta al servidor, no puede confiar en la identidad de la memoria. Incluso podría tener varias instancias en memoria de la misma instancia comercial. La instancia comercial está identificada por el id.

La comparación basada en la identificación es una cuestión de gusto. Personalmente, me gusta el código simple y confiable, y la comparación basada en identificador es simple y confiable, mientras que comparación profunda es siempre un poco arriesgado, propenso a errores, no se puede mantener. Así que terminas con el operador == comparando la identidad de la memoria e Igual comparando la identidad del negocio (y la base de datos).

NHibernate es la forma menos intrusiva de asignar un modelo de clase a una base de datos relacional que conozco. En nuestro gran proyecto tenemos claves primarias y propiedades de versión (se usan para el bloqueo optimista). Podría argumentar que esto es intrusivo, porque no se usa para la lógica comercial.

NH no requiere tener estas propiedades. (sin embargo, necesita una de las propiedades como clave principal.) Pero considere:

  • Simplemente funciona mejor, por ejemplo.bloqueo pesimista solo es posible con una propiedad apropiada,
  • más rápido: int id funciona mejor en muchas bases de datos luego otros tipos de datos
  • y más fácil: se desaconsejan las propiedades con un significado para el negocio por varias razones.

¿Por qué hacer su vida más difícil de lo necesario?


Editar: acaba de leer the documentation y encontraron que NHibernate hace no necesitan una propiedad id en la clase persistente! Si no tiene un identificador, you can't use some features. Se recomienda tenerlo, solo hace su vida más fácil.

+1

El paso cliente-servidor es un caso de uso específico: se puede resolver teniendo un proveedor de identidades o métodos de repositorio que se usan para este caso específico (GetId (objeto), GetById (id)). Además, no veo la diferencia entre la identidad de la memoria y la identidad comercial si utilizamos un ORM. Por lo que yo entiendo, dentro de una sesión siempre habrá un solo objeto con un ID dado (excepto las proyecciones, pero de todos modos no son interesantes para comparar). –

+2

Veo su punto de por qué no se recomienda la clave de datos empresariales, pero mi pregunta original es sobre el uso de una clave sustituta, pero solo en DB, donde corresponde. Por lo tanto, las desventajas no deberían aplicarse si NHibernate conoce la clave de DB sustituta; simplemente no quiero definirla en las entidades de mi dominio. –

+0

Quiere decir: SI usted no tiene una aplicación cliente-servidor, Y nunca tiene que pasar objetos de una sesión a otra (por ejemplo, transferencia en el tiempo, red, archivo) Y NO necesita una identificación de empresa sustituta, ENTONCES podría NHibernate administra la clave principal de la base de datos internamente. Esto es probablemente cierto, pero este sería un caso muy raro con limitaciones naturalmente fuertes. Podrías proponer esto como una mejora de la función en el Jira de NHibernate. O implementarlo como un parche. –

0

Tiene que tenerlo de una forma u otra para que el ORM pueda volver a la base de datos para realizar actualizaciones; Supongo que podría ser privado y oculto en una clase base, pero eso viola el concepto POCO.

+0

Ver la actualización de la publicación, creo que el ORM conoce Id de todos modos, solo puede usar el Mapa de identidad en reversa. –

+0

¿Está diciendo que el ORM realiza un seguimiento de todos los objetos actualmente en el sistema? No puedo decirlo, pero parece poco probable. –

+0

Dentro de una sesión, sí, debería. Según la configuración, la sesión puede ser una solicitud web o incluso un hilo completo o la vida útil de la aplicación. La razón es que cuando llamas a SubmitChanges, tienes que saber en qué cambios. Y AFAIK la mayoría de los ORM implementan también http://martinfowler.com/eaaCatalog/identityMap.html lo que también significa que tienen que saber lo que ya tienen. –

0

asumiendo que su identificación es su clave principal, no podrá guardar ningún dato de nuevo en la base de datos sin ella.
Por lo que respecta a iguales y GetHashCode ir, estos son para ordenar en listas donde se crea un pedido personalizado.

Gracias por la respuesta.

Varios de ellos sugieren que tener Id es la única forma de que el ORM haga una actualización de base de datos. No creo que este sea el caso. ORM ya realiza un seguimiento de todas las entidades cargadas desde el DB, por lo que debería ser capaz de obtener un ID internamente cuando lo necesite.

Estaría muy sorprendido si ese fuera el caso. Por lo general, crea una declaración de inserción solo a partir de las propiedades que ha definido.

+0

Ver la actualización de la publicación, creo que el ORM conoce Id internamente. –

+0

Estaría muy sorprendido si ese fuera el caso. Por lo general, crea una declaración de inserción solo a partir de las propiedades que ha definido. Sí, porque en la mayoría de los casos tiene sentido. Sin embargo, un buen ORM también tiene una versión anterior de su objeto y, en general, puede almacenar tanta información sobre su objeto como lo desee. Acabo de buscar en Google un ejemplo sobre cómo se pueden agregar datos adicionales a una inserción: http://www.dav-evans.com/?p=75. –

0

No hay otra opción para obtener el mismo objeto sin identidad.Por ejemplo, las personas tienen un número de seguridad social o código personal o algo que es único y podemos identificarlo por medio de él.

Puede usar una identidad natural pero es propensa a errores.

Solo cambie el nombre de Id to Identity. Se ve mejor en el modelo de dominio.

Las entidades se llaman entidades porque tienen identidad.

+0

Para situaciones web y otros casos similares, será suficiente algún tipo de IIdentityService que en realidad podría ser NHibernateIdentityService (pero es un caso específico cuando quiere hacer referencia a un objeto específico para su recuperación futura, no lo suficientemente genérico para el modelo de dominio). –

0

Normalmente incluyo el Id en el dominio como una clase de entidad base. No sé de ninguna otra manera de usar un ORM.

Un objeto en el dominio ya es único por su referencia, usar una identificación para determinar la singularidad/igualdad no es tan diferente en la práctica. Hasta ahora no he encontrado un efecto secundario serio en este enfoque.

-1

También puede usar múltiples campos para establecer la identidad, llamados claves compuestas. Esto requerirá más trabajo de tu parte, sin embargo.

aprender acerca de ellos here

+0

¿Significa que tendré que tener la misma clave principal en la tabla? –

+0

Bueno, sí, la identidad en nhib debe ser la identidad en la base de datos ... ese es el punto ... –

1

En Nh, no puede usar la igualdad de referencia para las instancias separadas. Esto te engorda por usar NH en clientes a los que les gustaría usar este comportamiento (en mi opinión, este es el comportamiento correcto, ¡NH no depende de la magia!).

En aplicaciones web o usos basados ​​en sesión donde puede ir a la base de datos en el ámbito de una sesión, creo que estoy en lo cierto al decir que puede confiar en la igualdad de referencia. Pero en un escenario de cliente inteligente, o más específicamente, cualquier escenario en el que dos ISessions comparten una instancia (una cargada desde o insertada en el db, y luego pasada al segundo), necesita los campos de id db almacenados junto con la instancia.

la segunda sesión siguiente no tenía idea de que la instancia que se está transfiriendo ya se ha insertado y requiere una actualización, e incluso si la cambió a una actualización, asumo que estoy en lo cierto al pensar que no va para saber la ID de DB de la clase.

class SomeEntityWithNoId 
{ 
public blah etc {} 
} 

class dao 
{ 

void DateMethod() 
{ 
var s1 = sessionFactory.OpenSession(); 
var instance = new SomeEntityWithNoId(); 
instance.Blah = "First time, you need to insert"; 
s1.Save(s1); //now instance is persisted, has a DB ID such as identity or Hilo or whatever 
s1.close(); 
var s2 = sessionFactory.OpenSession(); 
s2.Blah = "Now update, going to find that pretty hard as the 2nd session won't know what ID to use for the UPDATE statement"; 

s2.Update(instance); //results in boom! exception, the second session has no idea *how* to update this instance. 




} 
} 

Si usted está preocupado por el campo (s) de identificación, que estás en lo correcto en el pensamiento es en gran medida inútil para otra cosa que las preocupaciones de persistencia nada, puede que sean privadas, por lo que al menos este comportamiento y la semántica están encapsulados . Puede encontrar que este enfoque pone un poco de fricción en TDD.

Creo que tiene razón acerca de los mapas de identificación con respecto a NH al menos. Si la instancia es transitoria cuando se conecta por primera vez a la sesión, su tipo no necesita almacenar su ID de db en un campo. Creo que la sesión sabrá cómo gestionar su relación con el db. Estoy seguro de que puede extraer una prueba para probar este comportamiento; p

+0

Estoy de acuerdo con su publicación, pero no creo que el ejemplo proporcionado (2 sesiones posteriores con un objeto) sea un caso de uso común para NHibernate. Enviar objetos del servidor al cliente es otra historia, pero en este caso podrían ser DTO o tener un serializador personalizado que permita que se envíe/reciba Id. –

3

Normalmente, no tendrá el único modelo de dominio verdadero. Tendrá innumerables sesiones concurrentes y secuenciales, que deben coordinarse, y cada una de ellas contiene su propio modelo de dominio transaccional en miniatura, aislado. No tendrá las mismas instancias de objeto entre dos sesiones simultáneas o entre dos sesiones secuenciales. Pero necesitará alguna forma de asegurarse de que pueda mover la información de una sesión a otra.

Un ejemplo, por supuesto, es un par de/resource/list y/resource/show/id de URL (correspondiente a un par apropiado de acciones de controlador en asp.net mvc). Pasando de uno a otro, hay dos sesiones completamente independientes, pero necesitan comunicarse (a través de HTTP y el navegador) entre sí.

Incluso sin utilizar una base de datos, los objetos del modelo de su dominio aún necesitan alguna forma de identidad porque aún tendrá numerosos modelos de dominio en miniatura, aislados, no el único modelo de dominio verdadero; y tendrá todos estos modelos de dominio en sesiones independientes, tanto al mismo tiempo como una después de otra.

La uniformidad del objeto no es suficiente, porque los objetos no son los mismos entre sesiones aunque las entidades conceptuales subyacentes que representan son la misma entidad.

+2

Gracias por el punto bien descrito. Ver actualización de publicación 2. Acepto que necesita un sistema de referencia/identidad serializable si desea hacer/resource/show/id, pero parece una restricción específica de la web, no un requisito de dominio. Pero en cuanto a la igualdad, no me parece que haya una razón para comparar objetos de diferentes sesiones. –

+0

El patrón de sesión o unidad de trabajo requeriría que, incluso en una aplicación de escritorio sin base de datos, los objetos del modelo de dominio tengan identificadores persistentes únicos que sean los mismos en todas las sesiones, aunque los objetos mismos no sean los mismos en todas las sesiones. – yfeldblum

Cuestiones relacionadas