¿Cómo puedo editar una entidad usando el Código Marco de la entidad Primera aproximación?

StackOverflow https://stackoverflow.com/questions/4650077

  •  09-10-2019
  •  | 
  •  

Pregunta

he estado rompiendo mi pelo hacia fuera sobre esto durante días y antes de quedarse calvo por completo de tiempo para hacer todas las personas más inteligentes que yo cómo hacer esto.

Estoy utilizando Entity Framework 4 con el Código primera CTP 5 y MVC 3.

El mensaje de excepción en este momento es "Un objeto con la misma clave ya existe en la ObjectStateManager. El ObjectStateManager no puede realizar un seguimiento de múltiples objetos con la misma clave."

En primer lugar aquí es el controlador del formulario de edición se ha publicado en:

public ActionResult Save(ClientEntity postedClient)
    {
        try
        {
            if (ModelState.IsValid)
            {
                Base.clientInterface.Save(postedClient);
                return RedirectToAction("Index");
            }
        }
        catch (Exception)
        {

            throw;
        }

        SetupManageData(null, postedClient);
        return View("Manage");

    }

El método Save en la interfaz de cliente es la siguiente:

public void Save(ClientEntity theClient)
    {
        SetContext();


        if (theClient.clientId == 0)
            this.pContext.Clients.Add(theClient);
        else
        {
            ClientEntity existingClient = GetSingle(theClient.clientId); // Get the existing entity from the data store.

            // PseudoCode: Merge existingClient and theClient - Can this be done without using ObjectStateManager?               
            // PseudoCode: Attach merged entity to context so that SaveChanges will update it in the database - is this correct?
        }

        this.pContext.SaveChanges();

    }

    private void SetContext()
    {
        if (this.pContext == null)
            this.pContext = new PersistanceContext();           
    }

contexto Persistencia es la DBContext y se ve así:

public class PersistanceContext : DbContext
{
    public DbSet<ClientEntity> Clients { get; set; }
}
¿Fue útil?

Solución

¿Cuál es el estilo de vida de clientInterface? es un producto único o algo que lo mantiene vivo a través de múltiples peticiones?

Mi conjetura es que tiene una instancia en vivo de un contexto de base de datos que se utilizó para buscar a la entidad en la solicitud GET y cuando el POST trata de (re) añadir una entidad cliente al contexto del viejo está todavía allí y entran en conflicto.

Trate de destruir el objeto que está detrás de la clientInterface con cada petición. Tal vez utilizar un contenedor DI soportes que per-WebRequest estilos de vida por lo que no tienen que preocuparse por ello.

Espero que mi suposición era correcta y esto es de ayuda.

Otros consejos

Esto debería funcionar.

    if (theClient.clientId == 0)
    {
        this.pContext.Clients.Add(theClient);
    }
    else
    {
        ClientEntity existingClient = this.pContext.Clients.Single(o => o.ClientId == theClient.ClientId);

        // map properties
        existingClient.Name = theClient.name;
        // ....

    }

    this.pContext.SaveChanges();

[Editar]

Es más fácil (en mi humilde opinión) para dividir la creación y edición de objetos en 2 visitas separadas y evitar el mapeo de las propiedades que utilizo TryUpdateModel.

[HttpPost]
public ViewResult Edit(int clientID, FormCollection collection) 
{
    var client = pContext.Clients.SingleOrDefault(o => o.ID == clientID);

    if(!TryUpdateModel(client, collection)) 
    {
        ViewBag.UpdateError = "Update Failure";
    }
    else
    {
        db.SubmitChanges();
    }

    return View("Details", client); 
}

[HttpPost]
public ViewResult Create(FormCollection collection) 
{
    var client = new Client();

    if(!TryUpdateModel(client, collection)) 
    {
        ViewBag.UpdateError = "Create Failure";
    }
    else
    {
        db.Clients.Add(client);
        db.SubmitChanges();
    }

    return View("Details", client); 
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top