Search code examples
azureentity-framework-6linq-to-entitiesazure-sql-database

Loading multiple levels of nested navigation and collection properties with proxy disabled


I'm having a hard time figuring out how to do queries with levels of alternating collection and navigation properties with proxy and lazy loading disabled to serialize the result.

public ApplicationDbContext()
            : base("Debug")
        {
            this.Configuration.LazyLoadingEnabled = false;
            this.Configuration.ProxyCreationEnabled = false;
        }

The entities look like this (omitting non-navigation or non-collections):

public class Comprobante: ComprobanteGeneric 
{
}

public class ComprobanteGenericStructure
    public int Id { get; set; }
    [Required]
    public virtual Conceptos Conceptos { get; set; }
}

public class Conceptos
{
    public Conceptos()
    {
        Concepto = new List<Concepto>();
    }
    [ForeignKey("Comprobante")]
    public int Id { get; set; }
    [Required]
    public virtual ICollection<Concepto> Concepto { get; set; }
    public virtual Comprobante Comprobante { get; set; }
}

public class Concepto :RelatedComprobante
{
    [Key]
    public int Id { get; set; }
    public virtual OrderOfImpuestosForConceptos Impuestos { get; set; }
    public virtual Conceptos Conceptos { get; set; }
}

public class RelatedComprobante
{
    [ForeignKey("Comprobante")]
    public int ComprobanteId { get; set; }
    public virtual Comprobante Comprobante { get; set; }
}

public class OrderOfImpuestosForConceptos : RelatedComprobante
{
    public int Id { get; set; }
    public virtual TrasladosNode Traslados { get; set; }
    public virtual Retenciones Retenciones { get; set; }
}

public class TrasladosNode : RelatedComprobante
{
    public TrasladosNode()
    {
        Traslado = new HashSet<Traslado>();
    }
    [Key]
    public int Id { get; set; }
    [Required]
    public virtual ICollection<Traslado> Traslado { get; set; }
}

public class Traslado : RelatedComprobante
{
    public int Id { get; set; }
    public virtual TrasladosNode TrasladosNode { get; set; }
}

public class Retenciones : RelatedComprobante
{
    public Retenciones()
    {
        Retencion = new List<Retencion>();
    }
    public int Id { get; set; }
    [Required]
    public virtual ICollection<Retencion> Retencion { get; set; }
}

public class Retencion : RelatedComprobante
{
    public int Id { get; set; }
    public virtual Retenciones Retenciones { get; set; }
}

I need the whole graph. With lazy loading enabled it returns it all eventually but serialization takes several seconds and several queries to DB. I disabled it and tried the following query:

comprobantes = _db.Comprobante
            .Include(c => c.Conceptos.Concepto.Select(co => co.Impuestos.Retenciones).Select(r=>r.Retencion))
            .Include(c => c.Conceptos.Concepto.Select(co => co.Impuestos.Traslados).Select(t => t.Traslado));

However I get an empty concepto list:

[{
  "id": 324,
  "conceptos": {
    "concepto": []
  }
},
{
  "id": 340,
  "conceptos": {
    "concepto": []
  }
}
}]

Even simpler queries like the following yield the exact same results:

comprobantes = _db.Comprobante
            .Include(c => c.Conceptos.Concepto.Select(co => co.Impuestos));

I know is not the serialization for when I inspect the object while debugging is empty: Empty concepto array

What am I doing wrong?


Solution

  • Thanks to David comment I was able to build a working query(es):

    var comprobantes = _db.Comprobante
                .Include(b => b.Conceptos.Concepto.Select(c => c.Impuestos.Retenciones.Retencion))
                .Include(b => b.Conceptos.Concepto.Select(c => c.Impuestos.Traslados.Traslado));
    foreach (var comprobante in comprobantes)
    {
        _db.ComprobanteTraslado.Where(t => t.ComprobanteId == comprobante.Id);
        _db.ComprobanteRetencion.Where(r => r.ComprobanteId == comprobante.Id);
    }