Frage

I have 6 classes and I try to use linq to Entities to get the SiglaUF information of the last deeper table (in the view - MVC). The problem is I receive the following error:

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

The view is like that:

>     @model IEnumerable<DiskPizzaDelivery.Models.EnderecoCliente>
>     @foreach (var item in Model) {
>          @Html.DisplayFor(modelItem => item.CEP.Cidade.UF.SiglaUF)
>     }

The query that i use:

 var cliente = context.Clientes
       .Include(e => e.Enderecos)
       .Include(e1 => e1.Enderecos.Select(cep => cep.CEP))
       .SingleOrDefault();

The question is: How Can I improve this query to pre loading (eager loading) "Cidade" and "UF"?

See below the classes:

public partial class Cliente
    {
        [Key]
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
        public int IdCliente { get; set; }
        public string Email { get; set; }
        public string Senha { get; set; }
        public virtual ICollection<EnderecoCliente> Enderecos { get; set; }
    }
public partial class EnderecoCliente
    {
        public int IdEndereco { get; set; }
        public int IdCliente { get; set; }
        public string CEPEndereco { get; set; }
        public string Numero { get; set; }
        public string Complemento { get; set; }
        public string PontoReferencia { get; set; }
        public virtual Cliente Cliente { get; set; }
        public virtual CEP CEP { get; set; }
    }
public partial class CEP
    {
        public string CodCep { get; set; }
        public string Tipo_Logradouro { get; set; }
        public string Logradouro { get; set; }
        public string Bairro { get; set; }
        public int CodigoUF { get; set; }
        public int CodigoCidade { get; set; }
        public virtual Cidade Cidade { get; set; }
    }
public partial class Cidade
    {
        public int CodigoCidade { get; set; }
        public string NomeCidade { get; set; }
        public int CodigoUF { get; set; }
        public virtual ICollection<CEP> CEPs { get; set; }
        public virtual UF UF { get; set; }
        public virtual ICollection<UF> UFs { get; set; }
    }
public partial class UF
    {
        public int CodigoUF { get; set; }
        public string SiglaUF { get; set; }
        public string NomeUF { get; set; }
        public int CodigoCidadeCapital { get; set; }
        public virtual ICollection<Cidade> Cidades { get; set; }
        public virtual Cidade Cidade { get; set; }
    }

var cliente = context.Clientes
                .Where(c => c.Email == email)
                .Where(c => c.Senha == senha)
                .Include(e => e.Enderecos)
                .Include(e1 => e1.Enderecos.Select(cep => cep.CEP))
                .SingleOrDefault();

Thanks!

War es hilfreich?

Lösung

You can simply include the entire navigation path.

 var cliente = context.Clientes
       .Include(e => e.Enderecos)
       .Include(e1 => e1.Enderecos.Select(cep => cep.CEP.Cidade.UF))
       .SingleOrDefault();

Andere Tipps

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

You are getting this because IEnumerable.GetEnumerator() is being called on the DbQuery after your DbContext.Dispose has been called.

The typical reason for this occuring in ASP.Net MVC is the following code.

public class FooController : Controller
{
    public ActionResult Index()
    {
        using(var database = new DatabaseContext())
        {
            var query = from x in database.Foos
                        ...blah blah blah...
                        select x;
            return View(query);
        }
    }
}

This is subtitle. But by the time the view runs @foreach(var item in Model) (which implicitely calls IEnumerable.GetEnumerator() your Controller.Index() method has already returned, and hence your database context has been disposed.

There are two ways to fix this.

public class FooController : Controller
{
    public ActionResult Index()
    {
        using(var database = new DatabaseContext())
        {
            var query = from x in database.Foos
                        ...blah blah blah...
                        select x;
            return View(query.ToList());
        }
    }
}

This method ensures that we run IEnumerable.GetEnumerator() whilst the DbContext is still active. However I prefer the next method...

public class FooController : Controller
{
    private DatabaseContext _database = new DatabaseContext();

    public ActionResult Index()
    {
        var query = from x in database.Foos
                    ...blah blah blah...
                    select x;
        return View(query);         
    }

    public override Dispose()
    {
        _database.Dispose();
    }
}

The reason being is that you can then add .AsStreaming() and .AsNoTracking() to your query. This means that your POCO objects live only long enough to be written by the View, reducing your memory load.

The Answer is in the question itself

How can I Include Multiples Tables??

Just us INCLUDE, the Answer has already been pretty much explained by Scartag

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top