Skip to content

Latest commit

 

History

History
65 lines (49 loc) · 4.11 KB

File metadata and controls

65 lines (49 loc) · 4.11 KB

Немного об вездесущем IQueryable

IQueryable - это базовый интерфейс LINQ для анализа запросов к источникам данных. С помощью данного итерфейса требуемый запрос проходит через ряд фильтров и фактическая проекция данных определяется в последний момент (например, на прикладном уровне).

Интерфейс IQueryable не ответственен за фактическое выполнение запроса. Он лишь описывает запросы, которые должны быть выполнены. Выполнение запросов и материализация результатов - хадача конкретного провайдера LINQ. Проввайдеры LINQ связаны с фактической технологией, используемой для доступа к данным.

Примеры

  1. Не заканчивается вызовом .ToList(), .First() и т.п.
var queryProducts = (from p in CatalogServices.GetProductAsAvailableForSale())
                        orderby p.UnitsInStock descending
                        select new ProductDescriptor
                        {
                            Id = p.Id,
                            Name = p.Name,
                            UnitPrice = p.UnitPrice,
                            UnitsInStock = p.UnitsInStock,
                        }).Take(3);
  1. Заканчивается вызовом .SingleOrDefaultAsync()
var userName = _securityService.GetUserName();
var currentEmployee = await _database
            .Employees
            .AsNoTracking()
            .WhereEmployeeIsCUrrentUser(userName)
            .Select(employee =>
                new CurrentEmployeeDTO
                {
                    EmployeeId = employee.PersonalInformation.Id,
                    FirstName = employee.PersonalInformation.FirstName,
                    LastName = employee.PersonalInformation.LastName,
                    Email = employee.PersonalInformation.Email,
                    Identifier = employee.PersonalInformation.Identifier,
                    JobTitle = employee.JobTitle,
                    IsManager = employee.IsTeamManager,
                    TeamId = employee.TeamId,
                }).SingleOrDefaultAsync();

currentEmployee.PictureUrl = Url.Link("EmployeePicture", new { employeeId = currentEmployee.EmployeeId });

Интерфейс IQueryable позволяет определять запрос к провайдеру LINQ, такому как безе данных.

Однако выполнение запроса откладывается, поэтому его можно создавать в несколько этапов.

Доступ к базе данных не выполняется, пока вы не вызовете метод выполнения (например, .ToList()).

Например, когда вы запрашиваете все продукты, которые находятся в продаже, вы не получаете все 200000 записей, которые соответствуют данным критериям. Добавляя команду .Take(3), вы просто уточняете запрос. Сам запрос выполняется лишь тогда, когда вызывается следующий код:

var featuredProducts = query.Products.ToList();

Код SQL тогда имеет следующий вид:

SELECT TOP 3 ... WHERE ...

В итоге, вы передаёте интерфейс IQueryalbe через уровни, и каждый уровень по сути может добавлять фильтры, уточняя запрос. В итоге вы получаете просто подмножество данных, в которых нуждаетесь в определённом сценарии использования.