简体   繁体   中英

How to specify an Include inside a lambda expression

I have A Rack model and a Server Model. Currently when I want to retrieve single Server I do the following, to specify explicit loading:-

public Server FindAllServer(int id)
        {

            return project.Servers.Where(c => c.ServerID == id)
                .Include(a => a.OperatingSystem)
                .Include(a2 => a2.DataCenter)
                .Include(a3=>a3.Rack)
                .Include(a4=>a4.ServerModel)
                .Include(a5=>a5.Technology)
                .Include(a6=>a6.VirtualMachines)
                .Include(a7=>a7.TechnologyStatu)
                .Include(a8=>a8.TechnologyBackUpStatu)
                .Include(a9=>a9.TechnologyRole)
                .SingleOrDefault();
        }

But now I want to display a Rack and all its server/s,I did the following :-

 public Rack FindAllRack(int id)
        {

            return project.Racks.Where(c => c.RackID == id)
                .Include(a => a.Servers)
                .Include(a2 => a2.DataCenter)
                .Include(a3 => a3.Firewalls)
                .Include(a4 => a4.Routers)
                .Include(a5 => a5.Technology)
                .Include(a6 => a6.StorageDevices)
                .Include(a7=>a7.Switches)
                .Include(a8=>a8.Zone)
                .SingleOrDefault();
        }

so I am not sure how I can define to explicitly include all the navigation properties for the Server/s under a Rack, as I cannot write something such as:-

project.Racks.Where(c => c.RackID == id).Include(a => a.Servers.Include(………))

The problem is that in case I have 50 servers under a rack, then for each server there will be around 7 requests to retrieve the server navigation properties, so I will have around 350 requests !!!

I think you should be able to do this with the string-based overload of Include() by specifying a property path, eg

project.Racks.Where(c => c.RackID == id).Include("Servers.SomePropertyOfServer")

EDIT : After doing some more research, it appears this may also work:

project.Racks.Where(c => c.RackID == id).Include(a => a.Servers.Select(s => s.SomePropertyOfServer))

See this link , specifically the section entitled "Eagerly Loading Multiple Levels" for an example.

If all you need is the count of the various child objects, consider the following instead. It should issue a single request to the database only fetching up to 2 rows. Profile the request to make sure this is the case as I haven't tested it.

        return project.Racks.Where(c => c.RackID == id)
            .Select(a => new {
                serverCount = a.Servers.Count(),
                dataCenterCount = a.DataCenter.Count(),
                firewallCount = a.Firewalls.Count(),
                routerCount = a.Routers.Count(),
                technologyCount = a.Technology.Count(),
                storageDeviceCount = a.StorageDevices.Count(),
                switchCount = a.Switches.Count(),
                zoneCount = a.Zone.Count()
            }).SingleOrDefault();

Also, if you aren't planning on throwning an exception if you get more than one record, use FirstOrDefault instead of SingleOrDefault.

Have you tried this?

return project.Servers
              .Include(a => a.OperatingSystem)
              .Include(a2 => a2.DataCenter)
              .Include(a3=>a3.Rack)
              .Include(a4=>a4.ServerModel)
              .Include(a5=>a5.Technology)
              .Include(a6=>a6.VirtualMachines)
              .Include(a7=>a7.TechnologyStatu)
              .Include(a8=>a8.TechnologyBackUpStatu)
              .Include(a9=>a9.TechnologyRole)
              .Where(srv => srv.Rack.RackID == id);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM