2011-04-20 15 views
17

Recientemente comencé a usar Entity Framework, y ha sido un poco doloroso comprobar si realmente necesito agregar nuevos registros a la base de datos o no.En Entity Framework, ¿cuál es la diferencia entre Agregar y Adjuntar y cómo puedo resolver mi problema?

Si el Entidad tengo que añadir a la base de datos ya está en ella, yo sé, porque yo hago una consulta antes de insertarlo, y si existe, entonces guardo esa instancia porque necesito usarlo en algunas relaciones.

Supongamos que el nombre de mi entidad es Book.

El problema viene cuando la entidad no se encuentra en la base de datos, y lo hago:

Book b = //... 
modelContainer.AddToBooks(b); 

que fácilmente podría hacer:

modelContainer.SaveChanges() 

cada vez que añadir una nueva entidad (no importa qué entidad es), y esto funcionará bien, porque como estoy insertando un tipo de entrada a la vez, y comprobando si ya está en la base de datos, no tendré problemas de duplicación.

Pero, ¿y si quiero evitar llamar a SaveChanges() con tanta frecuencia?

En esta pregunta: Is is possible to check if an object is already attached to a data context in Entity Framework?, el autor de la pregunta proporciona un método de ese tipo de me ayuda en mi caso, pero no funciona si Add el objeto con el contexto en lugar de Attaching ella.

Mi pregunta (tal vez dos, pero muy relacionada) es: ¿Cuál es la diferencia entre Agregar y Adjuntar y cómo puedo resolver mi problema?

Editar:
Este es un ejemplo del problema que estoy teniendo.

Tengo una entidad Result que tiene una relación con dos entidades más: Trainer y Horse.

Obtengo los datos de una fuente externa, así que tengo que crear manualmente todas las entidades.

Cada vez que necesita para insertar una nueva Trainer, que hago:

var trainer = Trainer.CreateTrainer(Id) 

Entonces consultar la base para ver si un entrenador con el que Id ya está en la base de datos. Si es así, entonces reemplazo la variable trainer con la que está en la base de datos.

Si no es así, no puedo hacer dos cosas aquí:

  • Acople el entrenador para el contexto (puedo comprobar si ya existe el uso de la clave)
  • Añadir al entrenador al contexto (usando AddToTrainers(...))

El mismo proceso para Horse.

Ahora, cuando tengo que crear una nueva Result (que contiene un Trainer y una Horse), asigno el caballo anterior entrenador & a esa instancia resultado.

¿Qué debo hacer aquí para poder agregar al contexto el nuevo Result?

  • Si hay que adjuntar el entrenador/caballo, entonces cuando hay que adjuntar el resultado, me sale InvalidOperationException, me teling que el entrenador ya está en el contexto del objeto.
  • Si agrego el capacitador en lugar de adjuntarlo, aparece otro error (no puedo recordarlo ahora, pero me decía que un Entrenador ya estaba en la base de datos).

Importante:
El primer error se da cuando se fija el resultado, y el segundo cuando se hace SaveChanges().

Lo que quiero evitar aquí es llamar al SaveChanges() cada vez que agrego un resultado nuevo.

Respuesta

21

ObjectContext realiza un seguimiento interno de todas las entidades que fueron cargadas por contexto, adjuntas o agregadas. Solo estas entidades se pueden modificar en la base de datos cuando se invoca SaveChanges. Cada entidad tiene un ObjectStateEntry en el ObjectStateManager. Una de las propiedades principales de ObjectStateEntry es State. El estado es de enumeración de tipo EntityState que ofrece estos valores:

  • Agregado
  • Suprimido
  • Independiente
  • Modified
  • Sin cambios

Cada entidad cargada desde la base de datos está en Unchanged estado. Independiente es un estado especial. No encontrará ObjectStateEntry con estado separado en el ObjectStateManager. Pero si solicita ObjectStateManager para el ObjectStateEntry para la entidad no rastreada por el contexto, creará un nuevo ObjectStateEntry con el estado Detached.

Ahora la diferencia entre Attach y AddObject:

  • Attach - si se llama a este método ObjectContext se iniciará el seguimiento gráfico de objetos conjunto (entidad principal y todas las entidades relacionadas). Todas las entidades que no fueron seguidas se establecerán en el estado Unchanged.
  • AddObject - si llama a este método, ObjectContext también comenzará a rastrear el gráfico de objetos completos (entidad principal y todas las entidades relacionadas). La diferencia es que todas las entidades que no fueron seguidas se establecerán en Added state (= nuevos objetos que se deben establecer en la base de datos).
+0

@Ladislav Gracias por su respuesta. De acuerdo con mi problema, ¿cómo puedo evitar insertar una instancia de una entidad 'A' con una relación con una instancia de' B', cuando ya agregué/adjunté la instancia de 'B'? Solo quiero insertar la instancia de 'A', pero obtengo' InvalidOperationException' –

+0

Agregue un ejemplo a su pregunta. –

+0

@Ladislav Agregado. –

8

Sé que ya llegué un poco tarde a esta publicación, pero estaba buscando una solución similar ...y luego me encontré con este artículo de Microsoft que puede sucinta respuestas de las preguntas de la OP, y puede ayudar a futuro para que los espectadores ?:

Add/Attach and Entity States == (http://msdn.microsoft.com/en-us/data/jj592676.aspx)

Desde el artículo:

Este El tema cubrirá cómo agregar y adjuntar entidades a un contexto y cómo Entity Framework las procesa durante SaveChanges.

Y ver específicamente la última sección de esa página:

insertar o actualizar patrón: Un patrón común para algunas aplicaciones es que sea Añadir una entidad como nuevo (lo que resulta en una inserción de base de datos) o Adjunte una entidad como existente y márquela como modificada (lo que da como resultado una actualización de la base de datos) según el valor de la clave principal.

Cuestiones relacionadas