Using LINQ .Select() to cast into new type is TOO slow?

后端 未结 2 1568
长情又很酷
长情又很酷 2021-01-25 10:34

Current project, broke head over this problem:

Client Repository:

public class ClientRepository
{
    // Members
    private masterDataContext _db;

             


        
相关标签:
2条回答
  • 2021-01-25 11:05

    Wow. You do a lot of looping there. Each Where inside the loop ends up looping an array to find an item, every iteration in the loop.

    Make dictionaries of the clients, so that you can look them up qickly. That should give you a dramatic increase in speed:

    public ActionResult Index()
    {
        private ClientRepository _cr = new ClientRepository();
        var _retailclients = _cr.GetRetailClientNames().ToDictionary(c => c.id);
        var _corporateclients = _cr.GetCorporateClientNames().ToDictionary(c => c.id);
        var _visits = _db.GetAllServiceVisits();
    
        var _temp = _visits.Select(o => new ServiceVisitViewModel
            {
                service_visit = o,
                client = (o.client_type ? _corporateclients[o.client_id].name : _retailclients[o.client_id].name)
            }).ToArray();
    
        return View(_temp);
    }
    
    0 讨论(0)
  • 2021-01-25 11:08

    The Select statement makes a huge difference here - because it's changing what's being done at the database. (I'm assuming _db.GetAllServiceVisits() returns an IQueryable<T>.)

    You're fetching all the retail and corporate clients into memory already because you're using ToArray. Your Select call will (I suspect) then be sending all that data back to the database so that the Select and Where can be performed there. I suspect if you look in SQL profiler, it'll be a pretty odd query.

    If you force everything to be done client-side, it should be bassically the same as your latter approach. You can do that easily, with:

    var _visits = _db.GetAllServiceVisits().ToList();
    

    ... however, that means you're pulling all of three tables from your database each time you hit this page. That doesn't sound like a good plan to me.

    However, it would be better if you could do everything in the database without fetching all the retail and corportate clients into memory first.

    That may be as simple as changing your repository methods to return IQueryable<T> instead of IEnumerable<T>, and removing the calls to AsEnumerable.

    0 讨论(0)
提交回复
热议问题