aweyeahdawg
aweyeahdawg

Reputation: 1026

EF Core 3.0 .Include() chain taking ~5-10x longer than 2.2

I'm having trouble with a large EF Core query that has a lot of chained .Include(). I have a linq query that looks like this:

_context.Equipment.Include(x => x.Group)
                .Include(x => x.Status)
                .Include(x => x.Area)
                .Include(x => x.EquipmentType)
                .Include(x => x.Parts).ThenInclude(x => x.ChildrenParts)
                .Include(x => x.Parts).ThenInclude(x => x.ParentParts)
                .Include(x => x.Parts).ThenInclude(x => x.Vendor)
                .Include(x => x.Notes)
                .Include(x => x.Department)
                .Include(x => x.PMaintenance)
                .Include(x => x.SystemInfo).ThenInclude(x => x.SystemUsers)
                .Include(x => x.SystemInfo).ThenInclude(x => x.Frameworks)
                .Include(x => x.SystemInfo).ThenInclude(x => x.VideoCards)
                .Include(x => x.SystemInfo).ThenInclude(x => x.StorageDrives)
                .Include(x => x.SystemInfo).ThenInclude(x => x.Software)
                .Include(x => x.SystemInfo).ThenInclude(x => x.NetworkAdapters)
                .Include(x => x.SystemInfo).ThenInclude(x => x.Printers)
                .Include(x => x.MaintenanceHours)
                .Include(x => x.Attachments)
                .Include(x => x.Request)
                .FirstOrDefault(x => x.EquipmentId == id);

In EF Core 2.2, this took less than a few seconds to evaluate. Now on EF Core 3.0, it takes about 15 seconds to complete. What about EF Core 3 made this so slow? I read here that ef now creates one sql statement per linq query, but I don't see how the statement would have changed in this instance. Can I do something to this query that would decrease the execution time?

EDIT: This is on SQL Server v11.0.3

Upvotes: 4

Views: 1114

Answers (1)

rBalzer
rBalzer

Reputation: 367

Try it like this. You might need to change some of the "Select" and "SelectMany" options and the Id field names as you did not post the context.`

var query = _context.Equipment.Include(x => x.Group)
            .Include(x => x.Status)
            .Include(x => x.Area)
            .Include(x => x.EquipmentType)
            .Include(x => x.Notes)
            .Include(x => x.Department)
            .Include(x => x.PMaintenance)
            .Include(x => x.MaintenanceHours)
            .Include(x => x.Attachments)
            .Include(x => x.Request).FirstOrDefault(x => x.EquipmentId == id);

            query.Include(x => x.Parts).ThenInclude(x => x.ChildrenParts).SelectMany(x => x.Parts).Where(a => query.Select(q => q.PartsId).Contains(a.Id)).Load();
            query.SelectMany(x => x.Parts).SelectMany(x => x.ChildrenParts).Load();
            query.SelectMany(x => x.Parts).SelectMany(x => x.ParentParts).Load();
            query.SelectMany(x => x.Parts).Select(x => x.Vendor).Load();
            query.Include(x => x.SystemInfo).ThenInclude(x => x.SystemUsers).SelectMany(x => x.SystemInfo).Where(a => query.Select(q => q.SystemInfoId).Contains(a.Id)).Load();
            query.SelectMany(x => x.SystemInfo).SelectMany(x => x.Frameworks).Load();
            query.SelectMany(x => x.SystemInfo).SelectMany(x => x.VideoCards).Load();
            query.SelectMany(x => x.SystemInfo).SelectMany(x => x.StorageDrives).Load();
            query.SelectMany(x => x.SystemInfo).SelectMany(x => x.Software).Load();
            query.SelectMany(x => x.SystemInfo).SelectMany(x => x.NetworkAdapters).Load();
            query.SelectMany(x => x.SystemInfo).SelectMany(x => x.Printers).Load();

            query.ToList();

Hope this helps.

Upvotes: 1

Related Questions