Error saving data from a session in the database

0

I'm developing a sales system. Follow the link: Save Request - ASP.NET MVC

But when I finish the purchase and save the data in the database, I get the following error:

  

"An entity object can not be referenced by multiple instances of IEntityChangeTracker"

How can I resolve this?

public ActionResult SalvarCarrinho() 
{
    var carrinho = Session["Carrinho"] != null ? (Pedido)Session["Carrinho"] : new Pedido();

    contexto.Pedidos.Add(carrinho);
    contexto.SaveChanges();

    return RedirectToAction("Carrinho");
}

Give an error on this line:

 contexto.Pedidos.Add(carrinho);

Controller Full Code :

public ActionResult AdicionarCarrinho(int id)
{
    Pedido carrinho = Session["Carrinho"] != null ? (Pedido)Session["Carrinho"] : new Pedido();

    var produto= db.Produto.Find(id);

    if (produto != null)
    {
        var itemPedido = new ItemPedido();
        itemPedido.Produto = produto;
        itemPedido.Qtd = 1;


        if (carrinho.ItemPedido.FirstOrDefault(x => x.IdProduto == produto.IdProduto) != null)
        {
            carrinho.ItemPedido.FirstOrDefault(x => x.IdProduto == produto.IdProduto).Qtd += 1;
        }
        else
        {
            carrinho.ItemPedido.Add(itemPedido);
        }



        carrinho.ValorTotal = carrinho.ItemPedido.Select(i => i.Pedido).Sum(d => d.Preco);

        Session["Carrinho"] = carrinho;
    }

    return RedirectToAction("Carrinho");
}

public ActionResult Carrinho()
{
    Pedido carrinho = Session["Carrinho"] != null ? (Pedido)Session["Carrinho"] : new Pedido();

    return View(carrinho);
}


public ActionResult Remover(int id)
{
    var carrinho = Session["Carrinho"] != null ? (Pedido)Session["Carrinho"] : new Pedido();
    var itemExclusao = carrinho.ItemPedido.FirstOrDefault(i => i.IdItemPedido == id);
    carrinho.ItemPedido.Remove(itemExclusao);

    Session["Carrinho"] = carrinho;
    return RedirectToAction("Carrinho");
}

public ActionResult FinalizarCarrinho()
{
    var carrinho = Session["Carrinho"] != null ? (Pedido)Session["Carrinho"] : new Pedido();

    var id = Convert.ToInt32(Session["IdUsuario"]);
    var usuario = db.Usuario.FirstOrDefault(u => u.IdUsuario == id);
    carrinho.DtPedido = DateTime.Now;
    carrinho.Usuario = usuario;
    carrinho.StatusPedido = "esperando pagamento";
    carrinho.TipoPag = "boleto";
    db.Pedido.Add(carrinho);
    db.SaveChanges();

    return RedirectToAction("Carrinho");
}
    
asked by anonymous 03.12.2014 / 21:51

1 answer

1

I do not remember if I said this in another answer, but possibly the cause of the problem is this:

var itemPedido = new ItemPedido();
itemPedido.Produto = design; // Aqui você definiu um Produto (e de forma errada)
itemPedido.Qtd = 1;
itemPedido.IdProduto = produto.IdProduto; // Então aqui vai dar problema

Considering that you made the decision to use Id as a sequential integer, the chance of confusing the Entity Framework is great. I explain:

Defining an Id like this:

itemPedido.IdProduto = produto.IdProduto;

You are forcing a unmapped object in context into an mapped object ID in context. And here:

itemPedido.Produto = design;

You're putting another object (which I do not know where it came from, because it's possibly a collage of another answer I gave) that I do not know if it's mapped in context or not. By doing this, you are basically creating a produto that does not exist (or at least the context understands this), because it is the Id of an object with the contents of another object.

In this case, filling itemPedido.IdProduto is totally unnecessary , since you are already filling itemPedido.Produto . You should avoid filling in a Foreign Key Id directly, as the Entity Framework can understand that it is a new object (most likely this is your problem) and insert into the database something it should not.

Same thing for this code:

carrinho.IdUsuario = Convert.ToInt32(Session["IdUsuario"]);

The correct thing is you select the user and assign the object of Usuario to the cart, so that the Entity Framework understands where that user came from:

var usuarioId = Convert.ToInt32(Session["IdUsuario"]);
var usuario = db.Usuarios.FirstOrDefault(u => u.IdUsuario == usuarioId);
carrinho.Usuario = usuario;

EDIT

Based on the comments, apparently the objects that go to the session are saving the reference of a context that no longer exists, so before inserting products into the request, do the following:

var produto = db.Produto.Find(id);
db.Entry(produto).State = EntityState.Detached;

if (produto != null)
{
    var itemPedido = new ItemPedido();
    itemPedido.Produto = produto;
    itemPedido.Qtd = 1;

    ...

This ensures that you will be working with context-sensitive objects.

To save, you need to reposition the objects in context:

public ActionResult FinalizarCarrinho()
{
    var carrinho = Session["Carrinho"] != null ? (Pedido)Session["Carrinho"] : new Pedido();

    var id = Convert.ToInt32(Session["IdUsuario"]);
    var usuario = db.Usuario.FirstOrDefault(u => u.IdUsuario == id);

    foreach (var itemPedido in carrinho.ItemPedido) {
        db.Produtos.Attach(itemPedido.Produto);
    }

    carrinho.DtPedido = DateTime.Now;
    carrinho.Usuario = usuario;
    carrinho.StatusPedido = "esperando pagamento";
    carrinho.TipoPag = "boleto";
    db.Pedido.Add(carrinho);
    db.SaveChanges();

    return RedirectToAction("Carrinho");
}

I have not tested this solution, but I think it should work.

    
04.12.2014 / 18:51