简体   繁体   English

加入时缓慢的 LINQ 查询

[英]Slow LINQ Query on Join

I'm using EF 6 with .NET Core.我将 EF 6 与 .NET Core 一起使用。 I have written the following query to select some data into a custom object.我编写了以下查询以将一些数据选择到自定义对象中。 At the moment the main query returns over 25000 records.目前主查询返回超过 25000 条记录。 Then the filters are applied.然后应用过滤器。 This query is running very slow.此查询运行非常缓慢。 I'm just trying to find out if I'm doing any mistakes here.我只是想看看我是否在这里做错了。 Why it could be so slow and is the filtering happening on the memory rather than on the database side?为什么它会这么慢,并且过滤发生在内存而不是数据库端?

public IQueryable<TicketViewModel> GetTickets(int companyId, string locale, TicketFilterViewModel filters, Guid customerRef, int? take, int currentUser)
        {
            IQueryable<TicketViewModel> tickets = (from to in _context.Ticket
                                                   join co in _context.Company on to.CompanyId equals co.CompanyId
                                                   join con in _context.Contact on to.ContactId equals con.ContactId
                                                   join site in _context.Site on to.SiteId equals site.SiteId
                                                   join country in _context.Country on site.CountryId equals country.CountryId
                                                   join cus in _context.Customer on con.CustomerId equals cus.CustomerId
                                                   join tic_type in _context.TicketType on to.TicketTypeId equals tic_type.TicketTypeId
                                                   join ts in _context.TicketStatus on to.TicketStatusId equals ts.TicketStatusId
                                                   join sb in _context.ServiceBoard on to.ServiceBoardId equals sb.ServiceBoardId into ob1
                                                   from a in ob1.DefaultIfEmpty()
                                                   join u in _context.User on to.TechnitianId equals u.Id into ob2
                                                   from b in ob2.DefaultIfEmpty()
                                                   join pr in _context.Priority on to.PriorityId equals pr.PriorityId into ob3
                                                   from c in ob3.DefaultIfEmpty()                                                  
                                                   where to.CompanyId == companyId && (customerRef == Guid.Empty || cus.RefNo == customerRef)
                                                   && to.MergedIntoTicketId == null
                                                   select new TicketViewModel
                                                   {
                                                       CreatedOn = Helpers.Custom.UtcToStandardTime(locale, to.AddedOnUtc).ToString("dd/MM/yyyy hh:mm tt"),
                                                       CustomerName = cus.CustomerName,
                                                       TicketNumber = to.TicketNumber,
                                                       TicketTitle = to.TicketTitle,
                                                       RefNo = to.RefNo,
                                                       CompanyName = co.CompanyName,
                                                       ContactName = string.Concat(con.FirstName, " ", con.LastName),
                                                       SiteAddress = String.Concat(site.AddressLine1, ", ", site.AddressLine2, ", ", site.Suburb, ", ", site.State, ", ", site.PostCode, ", ", country.Name),
                                                       ServiceBoardName = a.BoardName,
                                                       TechnicianName = string.Concat(b.FirstName, " ", b.LastName),
                                                       PriorityName = c.PriorityName,
                                                       TicketStatus = ts.StatusName, //d.StatusName,
                                                       ServiceBoardId = to.ServiceBoardId,
                                                       TicketStatusId = to.TicketStatusId,
                                                       CustomerId = cus.CustomerId,
                                                       PriorityId = to.PriorityId,
                                                       ContractId = site.ContractId,
                                                       TechnitianId = to.TechnitianId,
                                                       TicketId = to.TicketId,
                                                       StatusCategoryId = ts.CategoryId,//,//d.CategoryId,
                                                       DueOnUtc = to.DueOnUtc,
                                                       DefaultStatusId = ts.DefaultId,//d.DefaultId,
                                                       ClosedOnUtc = to.ClosedOnUtc,
                                                       ResolvedOnUtc = to.ResolvedOnUtc,
                                                       InitialResponseMade = to.InitialResponseMade,
                                                       TicketTypeId = to.TicketTypeId,
                                                       TicketTypeName = tic_type.TicketTypeName

                                                   }).OrderByDescending(o => o.TicketNumber);


            bool isFiltersHit = false;

            if (filters != null)
            {
                if (tickets != null && tickets.Count() > 0 && filters.serviceboard_selectedItems != null && filters.serviceboard_selectedItems.Count > 0)
                {
                    isFiltersHit = true;

                    tickets = tickets.Where(x => x.ServiceBoardId != null && filters.serviceboard_selectedItems.Select(o => o.serviceBoardId).Contains(x.ServiceBoardId.Value));

                }

                if (tickets != null && tickets.Count() > 0 && filters.status_selectedItems != null && filters.status_selectedItems.Count > 0)
                {
                    isFiltersHit = true;

                    tickets = tickets.Where(x => x.TicketStatusId != null && filters.status_selectedItems.Select(o => o.ticketStatusId).Contains(x.TicketStatusId.Value));

                }

                if (tickets != null && tickets.Count() > 0 && filters.type_selectedItems != null && filters.type_selectedItems.Count > 0)
                {
                    isFiltersHit = true;

                    tickets = tickets.Where(x => filters.type_selectedItems.Select(o => o.ticketTypeId).Contains(x.TicketTypeId));

                }

                if (tickets != null && tickets.Count() > 0 && filters.technician_selectedItems != null && filters.technician_selectedItems.Count > 0)
                {
                    isFiltersHit = true;

                    tickets = tickets.Where(x => x.TechnitianId != null && filters.technician_selectedItems.Select(o => o.id).Contains(x.TechnitianId.Value));

                }

                if (tickets != null && tickets.Count() > 0 && filters.customer_selectedItems != null && filters.customer_selectedItems.Count > 0)
                {
                    isFiltersHit = true;

                    tickets = tickets.Where(x => x.CustomerId != 0 && filters.customer_selectedItems.Select(o => o.customerId).Contains(x.CustomerId));

                }

                if (tickets != null && tickets.Count() > 0 && filters.priority_selectedItems != null && filters.priority_selectedItems.Count > 0)
                {
                    isFiltersHit = true;

                    tickets = tickets.Where(x => x.PriorityId != null && filters.priority_selectedItems.Select(o => o.priorityId).Contains(x.PriorityId.Value));

                }

                if (tickets != null && tickets.Count() > 0 && filters.contract_selectedItems != null && filters.contract_selectedItems.Count > 0)
                {
                    isFiltersHit = true;

                    tickets = tickets.Where(x => x.ContractId != null && filters.contract_selectedItems.Select(o => o.contractId).Contains(x.ContractId.Value));

                }

                if (tickets != null && tickets.Count() > 0 && filters.source_selectedItems != null && filters.source_selectedItems.Count > 0)
                {
                    isFiltersHit = true;

                    tickets = tickets.Where(x => x.SourceId != 0 && filters.source_selectedItems.Select(o => o.item_id).Contains(x.SourceId));

                }

            }


            if (take.HasValue)
                return tickets.Take(take.Value);

            return tickets;
        }

If you compose the query based on your conditions from the filters, you will see a big improvement.如果您根据过滤器中的条件编写查询,您会看到很大的改进。 Meaning, create a base query ( base and minimum conditions ) and then add the conditions one by one, depending on what your filters are.意思是,创建一个基本查询(基本条件和最小条件),然后根据您的过滤条件一一添加条件。 Execute the query after all filters are checked.在检查所有过滤器后执行查询。

PS: you don't really need to call tickets.Count() on every filter. PS:你真的不需要在每个过滤器上调用tickets.Count() Do it once, in the beginning.一开始就做一次。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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