Search code examples
c#entity-frameworkasp.net-mvc-5eager-loading

Entity Framework 6 Eager loading large object with many children and subchildren


I am migrating a project from lazy loading to eager loading.

I need to get a large object with all it's children, serialise it and send to front end's SPA app.

I built massive query, but it takes too much memory (as shown in VS's data diagnostic tools, the memory usage jumps by 200mb, the object itself is ~60KB when serialised to JSON )

Include(x => x.Privileges)
.Include(x => x.Team.Branch)
.Include(x => x.Equality)
.Include(x => x.AddressDetails).Include(x => x.ContactDetails)

.Include(x => x.EmployeeDetails.GeneralUnavailability)
.Include(x => x.EmployeeDetails.EligibilityDocuments.Select(z => z.Document.Priviliges))
.Include(x => x.EmployeeDetails.Position.PositionPayRuleExceptions).Include(x => x.EmployeeDetails.Position.PositionPayRuleExceptions.Select(z => z.PayRule)).Include(x => x.EmployeeDetails.Position.DefaultOffer)


.Include(x => x.TransportationMode.ProofOfLicence.Priviliges).Include(x => x.TransportationMode.ProofOfInsurance)

.Include(x => x.UserAcademicQualifications.Select(z => z.AcademicQualification)).Include(x => x.UserAcademicQualifications.Select(z => z.AcademicQualificationScan.Priviliges))

.Include(x => x.ProfessionalRegistrations.Select(z => z.Body)).Include(x => x.ProfessionalRegistrations.Select(z => z.ProfessionalRegistrationScan.Priviliges))
.Include(x => x.Unavailabilities.Select(z => z.AbsenceType)).Include(x => x.Unavailabilities.Select(z => z.Document.Priviliges))
.Where(x=>x.Id=1)

I am new to making queries with ef6...because I was using lazy loading until now. Is there a way to optimise it?

Priviliges is a list of Privilige model

Document,ProfessionalRegistrationScan,AcademicQualificationScan,ProofOfInsurance,ProofOfLicence are using File model which has many to many relation Priviliges.

Thank you for your help

UPDATE

Tried using .AsNoTracking() as a test..and memory usage jumps by ~100mb with it. Which is still kinda high for ~60kb object...


Solution

  • So..the only optimisation I found ,which will keep track of entities is

    app = db.Users.Include(x => x.Privileges)
         .Include(x => x.Team.Branch)
         .Include(x => x.Equality)
         .Include(x => x.AddressDetails)
         .Include(x => x.ContactDetails).FirstOrDefault(x=>x.Id==3);
    
    app = db.Users.Include(x => x.ApplicantDetails.ApplicantOffers.Select(z => z.Offer))
            .Include(x => x.ApplicantDetails.ApplicantOffers.Select(z => z.OfferDocument))
            .Include(x =>x.ApplicantDetails.AppliedPosition.PositionPayRuleExceptions)
           .Include(x => x.ApplicantDetails.AppliedPosition.DefaultOffer)
           .Include(x => x.ApplicantDetails.Branch.AddressDetails).FirstOrDefault(x=>x.Id==3);
    

    Basically, divide it all into chunks. It still less queries than Lazy loading.

    Update: Same thing works for ef.core . Just split it into chunks