Solucionado (ver solução)
Solucionado
(ver solução)
8
respostas

Cap.4.Recuperando dados. Ex 5:Busca de produtos por nome da categoria.

Olá, estou recebendo o seguinte erro ao tentar cadastrar um novo produto:

´´´

Erro de Servidor no Aplicativo '/'.

The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.

Descrição: Ocorreu uma exceção sem tratamento durante a execução da atual solicitação da Web. Examine o rastreamento de pilha para obter mais informações sobre o erro e onde foi originado no código.

Detalhes da Exceção: System.ObjectDisposedException: The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.

Erro de Origem:

Linha 20:

@produto.Preco Linha 21: Linha 22: @if(produto.Categoria != null) { Linha 23: @produto.Categoria.Nome Linha 24: }

Arquivo de Origem: c:\repos\Alura_EFWeb\LojaWebEF\LojaWebEF\Views\Shared_ListaProdutos.cshtml Linha: 22

´´´

Segue o código do DAO:

'''

using LojaWebEF.Entidades; using System; using System.Collections.Generic; using System.Data; using System.Data.Entity; using System.Linq; using System.Web;

namespace LojaWebEF.DAO { public class ProdutosDAO { private EntidadesContext _contexto;

public ProdutosDAO(EntidadesContext contexto) { this._contexto = contexto; }

public void Adiciona(Produto produto) { _contexto.Produtos.Add(produto); }

public void Remove(Produto produto) { _contexto.Produtos.Remove(produto); }

public void Atualiza(Produto produto) { _contexto.Entry(produto).State = EntityState.Modified; }

public Produto BuscaPorId(int id) { return _contexto.Produtos.Find(id); }

public IEnumerable Lista() { return _contexto.Produtos.ToList(); }

public IEnumerable ProdutosComPrecoMaiorDoQue(decimal? preco) { decimal minimo = preco.GetValueOrDefault(0);

var busca = from p in _contexto.Produtos where p.Preco > minimo select p; return busca.ToList(); }

public IEnumerable ProdutosDaCategoria(string nomeCategoria) { var busca = from p in _contexto.Produtos where p.Categoria.Nome == nomeCategoria select p; return busca.ToList(); }

public IEnumerable ProdutosDaCategoriaComPrecoMaiorDoQue(decimal? preco, string nomeCategoria) { return new List(); }

public IEnumerable ListaPaginada(int paginaAtual) { return new List(); }

public IEnumerable BuscaPorPrecoCategoriaENome(decimal? preco, string nomeCategoria, string nome) { return new List(); } } }

'''

Este é o código do ProdutosController:

''' using LojaWebEF.DAO; using LojaWebEF.Entidades; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc;

namespace LojaWebEF.Controllers { public class ProdutosController : Controller { private ProdutosDAO _dao;

public ProdutosController(ProdutosDAO dao) { _dao = dao; } // // GET: /Produtos/ public ActionResult Index() { IEnumerable produtos = _dao.Lista(); return View(produtos); }

public ActionResult Form() { return View(); }

public ActionResult Adiciona(Produto produto) { _dao.Adiciona(produto); return RedirectToAction("Index"); }

public ActionResult Remove(int id) { return RedirectToAction("Index"); }

public ActionResult Visualiza(int id) { Produto p = _dao.BuscaPorId(id); return View(p); }

public ActionResult Atualiza(Produto produto) { return RedirectToAction("Index"); }

public ActionResult ProdutosComPrecoMinimo(decimal? preco) { ViewBag.Preco = preco; IEnumerable produtos = _dao.ProdutosComPrecoMaiorDoQue(preco); return View(produtos); }

public ActionResult ProdutosDaCategoria(string nomeCategoria) { ViewBag.NomeCategoria = nomeCategoria; IEnumerable produtos = _dao.ProdutosDaCategoria(nomeCategoria); return View(produtos); }

public ActionResult ProdutosDaCategoriaComPrecoMinimo(decimal? preco, string nomeCategoria) { ViewBag.Preco = preco; ViewBag.NomeCategoria = nomeCategoria; IEnumerable produtos = new List(); return View(produtos); }

public ActionResult BuscaDinamica(decimal? preco, string nomeCategoria, string nome) { ViewBag.Preco = preco; ViewBag.Nome = nome; ViewBag.NomeCategoria = nomeCategoria;

IEnumerable produtos = new List(); return View(produtos); } public ActionResult ListaPaginada(int? pagina) { int paginaAtual = pagina.GetValueOrDefault(1); ViewBag.Pagina = paginaAtual; IEnumerable produtos = new List(); return View(produtos); } } }

'''

8 respostas

Olá Rafael! Tudo beleza?

Isso aconteceu depois que você fez algo em específico, alguma alteração?

Oi, Gabriel! Na verdade, eu só percebi esse problema agora, ao realizar o exercício 5 da parte 4 do curso.

Percebi porque, quando tento recuperar os produtos com o código apresentado como resposta do instrutor, obtenho esse mesmo erro.

O erro explica que o objeto context não está mais disponível, que o mesmo teria sido "disposed".

Daí eu resolvi testar a inclusão de um objeto pois, se o contexto estivesse "indisponível", essa inclusão não ocorreria.

Dito e feito. Mesmo erro.

Poderia ser algum erro com o Ninject?

Eu estou prosseguindo com o curso, pois estou perdendo muito tempo com essa parte de dados... Acho que esses dois tópicos precisam de uma revisão...

Tanto o NHibernate, quanto o Entity Framework estão sendo os capítulos mais fracos do curso. Muitos erros, muitas inconsistências entre o vídeo e os exercícios propostos. Ora se utiliza uma aplicação local, ora web... Nem sempre qual aplicação deve ser utilizada para executar as tarefas está claro...

O material é muito bom, mas precisa ser aprimorado.

Gabriel: Não sei se há regras contra isso, mas segue aqui um link para o meu projeto: https://github.com/rqguzman/Alura_EFWeb

Se este tipo de prática não é permitido, registro antecipadamente o meu pedido de desculpas.

Rafael, não tem problema nenhum postar seu projeto aqui :)

Então, eu baixei seu projeto aqui e fui tentar cadastrar um produto. E ele não está dando erro nenhum, simplesmente redireciona para a listagem de produtos. Isso porque o método Adiciona do ProdutosController está assim:

public ActionResult Adiciona(Produto produto)
        {
            return RedirectToAction("Index");
        }

Estou olhando no lugar errado? :)

Gabriel: Obrigado pela ajuda!

a versão que estou executando é a versão do branch "desenvolvimento", que deve estar mais atualizada que o branch "master". Mesmo assim, executei um "clean solution", fiz um novo build do projeto e estou obtendo êxito no cadastro de produtos. Vou testar as outras funcionalidades(listagens) para ver se encontro o problema do "Object disposed Exception" que relatei na abertura do tópico.

Gabriel: Acabei de testar meu projeto. 3 operações de busca estão apresentando o mesmo erro "Object disposed exception":

Busca de Produtos com preço mínimo; Busca de Produtos pelo nome da categoria; Busca de Produtos pelo nome da categoria, com preço mínimo;

Fica evidente que, se resolvermos a questão das duas buscas anteriores, a última será provavelmente resolvida.

Fiz um push de meu projeto, no branch "desenvolvimento", para que Vc encontre as mesmas condições que eu estou encontrando aqui. Acrescentei uma pasta "00_PrintScreens" para o print das telas de erro que estou recebendo.

Uma dúvida adicional: Nas respostas do instrutor, os controllers (de produtos e categorias) estão sem as ViewBags. Em meu projeto elas permanecem. Embora eu tenha testado comentar as ViewBags, para checar se essa era a causa do erro e nada de diferente tenha ocorrido, gostaria de saber o porquê do instrutor as ter deletado...

Rafael, dei uma olhada aqui.

O que acontece é o seguinte: depois que a action ProdutosComPrecoMinimo por exemplo é executada, o método OnActionExecuted do seu filtro SaveChangesFilter é executado. Isso porque você registrou esse filtro como global. Aí, quando a listagem vai ser carregada pela sua view dá esse erro porque você deu dispose() no contexto do EF.

Eu não me lembro exatamente, o curso pede para você colocar esse filtro SaveChanges como global?

Em quais exercícios as Viewbags não estão mais na resposta do instrutor? Poderia passar os links, por favor? :)

solução!

Olá Gabriel, desculpe a demora. Precisei revisar tudo o que já havia feito para lhe dar respostas fundamentadas.

Com relação ao metodo "_context.Dispose()": de fato, durante os vídeos, logo no início do curso, o método está presente, mas ele não aparece depois que é criado o filtro global. Eu imaginei que o instrutor houvesse esquecido, uma vez que não há nenhum comentário sobre o porquê dele ter sido removido.

Sim, o filtro deve ser global de acordo com o vídeo e com as explicações: https://www.alura.com.br/course/entity-framework/section/2/exercise/13

Por fim, seguem alguns dos links onde as respostas do instrutor para os exercícios não possuem as viewbags: 1 - https://www.alura.com.br/course/entity-framework/exercise/7859/analyse 2 - https://www.alura.com.br/course/entity-framework/exercise/7860/analyse 3 - https://www.alura.com.br/course/entity-framework/exercise/7862/analyse

Suprimi a linha com o método ".Dispose()" e toda a aplicação passou a funcionar da maneira desejada.

Obrigado por sua atenção!