2010-10-13 18 views
117

He estado trabajando recientemente con Entity Framework 4, y estoy un poco confundido sobre cuándo usar ObjectSet.Attach y ObjectSet.AddObject.Entity Framework 4 - AddObject vs Attach

Desde mi entendimiento:

  • Uso "Adjuntar" cuando una entidad ya existe en el sistema
  • Uso "AddObject" al crear una marca nueva Entidad

lo tanto, si i' m creando una nueva Persona, hago esto.

var ctx = new MyEntities(); 
var newPerson = new Person { Name = "Joe Bloggs" }; 
ctx.Persons.AddObject(newPerson); 
ctx.SaveChanges(); 

si estoy modificación de una persona existente, hago esto:

var ctx = new MyEntities(); 
var existingPerson = ctx.Persons.SingleOrDefault(p => p.Name = "Joe Bloggs" }; 
existingPerson.Name = "Joe Briggs"; 
ctx.SaveChanges(); 

tener en cuenta, este es un ejemplo muy simple. En realidad estoy usando Pure POCO (sin generación de código), el patrón Repository (no se ocupan de ctx.Persons), y la Unidad de trabajo (no se ocupan de ctx.SaveChanges). Pero "debajo de las sábanas", lo anterior es lo que sucede en mi implementación.

Ahora, mi pregunta - Todavía tengo que encontrar un escenario en el que he tenido que usar Acople.

¿Qué es lo que falta aquí? ¿Cuándo necesitamos usar Adjuntar?

EDITAR

Solo para aclarar, estoy buscando ejemplos de cuándo utilizar Adjuntar sobre AddObject (o viceversa).

EDIT 2

La respuesta a continuación es correcta (que acepté), pero que me gustaría añadir otro ejemplo donde Adjuntar sería útil.

En mi ejemplo anterior para modificando una Persona existente, se están ejecutando dos consultas.

Uno para recuperar la Persona (.SingleOrDefault), y otro para realizar la ACTUALIZACIÓN (.SaveChanges).

Si (por alguna razón), ya sabía que "Joe Bloggs" existía en el sistema, ¿por qué hacer una consulta adicional para obtenerlo primero? Podría hacer esto:

var ctx = new MyEntities(); 
var existingPerson = new Person { Name = "Joe Bloggs" }; 
ctx.Persons.Attach(existingPerson); 
ctx.SaveChanges(); 

Esto dará como resultado que solo se ejecute una instrucción UPDATE.

+0

Attach también se usa en MVC ahora en días cuando se vuelven a poner modelos directamente en EF. Funciona bastante bien y ahorra un montón de líneas de código. – ppumkin

Respuesta

146

ObjectContext.AddObject y ObjectSet.AddObject:
El AddObject método es para la adición de objetos recién creados que hacen no existen en la base de datos.La entidad obtendrá un EntityKey temporal generado automáticamente y su EntityState se establecerá en Se agregó. Cuando se llama a SaveChanges, el EF tendrá claro que esta entidad debe insertarse en la base de datos.

ObjectContext.Attach y ObjectSet.Attach:
Por otro lado, Acople se utiliza para las entidades que ya existan en la base de datos. En lugar de establecer la EntityState a Agregado, Adjuntar resultados en una Sin cambios EntityState, lo que significa que no ha cambiado desde que se adjunta al contexto. Se supone que los objetos que está adjuntando existen en la base de datos. Si modifica los objetos después de que se han adjuntado, cuando llama a SaveChanges, el valor de EntityKey se usa para actualizar (o eliminar) la fila adecuada al encontrar su ID coincidente en la tabla db.

Además, utilizando el método Adjuntar, puede definir las relaciones entre las entidades que ya existen en el ObjectContext pero que tienen no han conectado automáticamente. Básicamente, el objetivo principal de Attach es conectar entidades que ya están asociadas al ObjectContext y que no son , no nuevas, por lo que no puede usar Adjuntar para adjuntar entidades cuyo EntityState está agregado. Tienes que usar Add() en este caso.

Por ejemplo, vamos a asumir que su entidad Persona tiene una propiedad de navegación llamado Direcciones que es una colección de Dirección entidad. Digamos que usted ha leído los dos objetos de contexto, pero que no están relacionados entre sí y que desea que sea así:

var existingPerson = ctx.Persons.SingleOrDefault(p => p.Name = "Joe Bloggs" }; 
var myAddress = ctx.Addresses.First(a => a.PersonID != existingPerson.PersonID); 
existingPerson.Addresses.Attach(myAddress); 
// OR: 
myAddress.PersonReference.Attach(existingPerson) 
ctx.SaveChanges(); 
+0

Gracias por la respuesta, entiendo la definición de los dos (también conocido como los dos primeros párrafos). Pero no entiendo un escenario donde NECESITO usar Adjuntar. Tu último párrafo realmente no tiene sentido para mí (básicamente se lee como una combinación de los dos primeros párrafos), ¿puedes darme un ejemplo de dónde usaría "Adjuntar" en mi escenario anterior? Eso es realmente lo que estoy buscando: ejemplos, no definiciones. Realmente aprecio tu tiempo sin embargo. :) – RPM1984

+1

No hay problema, he agregado un fragmento de código para aclarar el último párrafo, ya que puedes ver que tenemos 2 objetos no relacionados y Adjuntar nos ayuda a relacionarlos entre sí. El otro ejemplo sería usar el método Attach() para Adjuntar una "entidad separada" al contexto (Hay varios motivos por los que podría desear que una entidad independiente se adjunte de nuevo al contexto) –

+0

Sí, lo tengo ahora. Acabo de ver un video de TechEd sobre EF4 (por Julie Lerman), que mostró un ejemplo. Es posible que tengas una entidad que NO recuperaste de una consulta (es decir, que esté desconectada), pero sabes que existe, por lo tanto, usas Adjuntar para realizar una ACTUALIZACIÓN en esa entidad. Tiene sentido, aunque sigo luchando por imaginar un escenario en el que tendría una entidad "desconectada". Gracias por tu ayuda. – RPM1984

-8

¿Qué pasa solamente refiriéndose a la clave principal en lugar de fijarlo?

es decir:

var existingPerson = ctx.Persons.SingleOrDefault(p => p.Name = "Joe Bloggs" }; 
var myAddress = ctx.Addresses.First(a => a.PersonID != existingPerson.PersonID); 
existingPerson.AddressId = myAddress.Id // not -> existingPerson.Addresses.Attach(myAddress); 
// OR: 
myAddress.Person.Id = existingPerson.Id // not -> myAddress.PersonReference.Attach(existingPerson); 
ctx.SaveChanges(); 
23

Ésta es una respuesta tardía pero podría ayudar a otros que encuentran esto.

Básicamente, una entidad "desconectado" puede ocurrir cuando se manipula una entidad fuera de la "usando" ámbito.

Employee e = null; 

using (var ctx = new MyModelContainer()) 
{ 
    e = ctx.Employees.SingleOrDefault(emp => emp .....); 
} 

using (var ctx2 = new MyModelContainer()) 
{ 
    e; // This entity instance is disconnected from ctx2 
} 

Si introduce otro "por medio de" alcance a continuación, la "e" variable se desconecta porque pertenece a la anterior "utilizando" el alcance y desde la anterior "El uso de" alcance se destruye a continuación "e" se desconecta .

Así es como lo entiendo.

+2

El ejemplo de Tchi es un ejemplo excelente y simple: sí, la variable Employee debe declararse afuera. prueba e.Address.Calle fuera del alcance y vea una ventana emergente de excepción de referencia nula. Si adjuntas, la aplicación no tendrá que volver al DB para el empleado en el segundo ámbito. – Steve

6

Esta es una cita de Programming Entity Framework: DbContext

Calling Eliminar en una entidad que no es seguido por el contexto, se producirá un InvalidOperationException a ser lanzado.El Entity Framework arroja esta excepción porque no está claro si la entidad que está intentando eliminar es una entidad existente que debe marcarse para su eliminación o una nueva entidad que simplemente debe ignorarse. Por este motivo, no podemos usar simplemente Eliminar para marcar una entidad desconectada como Eliminada; tenemos que adjuntarlo primero.

private static void TestDeleteDestination() 
{ 
    Destination canyon; 
    using (var context = new BreakAwayContext()) 
    { 
     canyon = (from d in context.Destinations 
     where d.Name == "Grand Canyon" 
     select d).Single(); 
    } 
    DeleteDestination(canyon); 
} 
private static void DeleteDestination(Destination destination) 
{ 
    using (var context = new BreakAwayContext()) 
    { 
     context.Destinations.Attach(destination); 
     context.Destinations.Remove(destination); 
     context.SaveChanges(); 
    } 
} 

El método TestDeleteDestination simula una aplicación cliente ir a buscar un destino existente desde el servidor y luego pasarlo al método DeleteDestination en el servidor. El método DeleteDestination utiliza el método Attach para que el contexto sepa que es un Destino existente. Luego, el método Remove se usa para registrar el Destination para su eliminación

Cuestiones relacionadas