Как я могу «расширить» результаты IQueryable на основе диапазона значений? - PullRequest
0 голосов
/ 08 мая 2019

Я пытаюсь определить способ использования Linq в IQueryable для "расширения" сущности в несколько результатов запроса на основе диапазона значений.В частности, расширяйте результаты на каждый день между начальной и конечной датой включительно.

Ниже перечислены объекты, вызывающие озабоченность (которые были сокращены и для ясности удалены аннотации):

public class Location {
    public int Id { get; set; }
    public string Name { get; set; }
}
public class WorkAssignment {
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime Start { get; set; }
    public DateTime End { get; set; }
    public virtual Location Location { get; set; }
    public int LocationId { get; set; }
}

Например, скажем, у нас есть:

Местоположения:

Id    Name
 1    Habitat
 2    Church

Рабочие задания:

Id   Name         Start         End      LocationId
 1   Jim       29-Apr-2019   3-May-2019      1
 2   Natasha    4-May-2019   7-May-2019      2
 3   Jennifer   5-May-2019   6-May-2019      2

Я бы хотелполучить следующее с использованием Linq, предпочтительно с использованием свободно используемых методов интерфейса.Важно выполнить «расширение» в запросе (что делает базу данных ответственной).Полный набор данных и ссылочные объекты составляют large , и я не хочу материализоваться, используя операторы .ToList() и foreach.

WorkerName    Date      LocationId   LocationName
Jim        29-Apr-2019      1          Habitat
Jim        30-Apr-2019      1          Habitat
Jim         1-May-2019      1          Habitat
Jim         2-May-2019      1          Habitat
Jim         3-May-2019      1          Habitat
Natasha     4-May-2019      2          Church
Natasha     5-May-2019      2          Church
Natasha     6-May-2019      2          Church
Natasha     7-May-2019      2          Church
Jennifer    5-May-2019      2          Church
Jennifer    6-May-2019      2          Church

Конечная цель заключается в получении вышеуказанного "расширение ", чтобы сгруппировать по расположению (упорядочено по LocationName), затем сгруппировать по дате (упорядочено по возрастанию), а затем по имени, чтобы предоставить листы входа для работника.Листы входа сгруппированы по местоположению, а затем по дате.На каждом листе будут перечислены рабочие для определенного местоположения на определенную дату.

Я выяснил запрос на группировку (спасибо Джону Скиту и всем его удивительным SO-ответам).Мне просто нужна помощь с вышеупомянутым расширением, если это вообще возможно сделать в IQueryable.

1 Ответ

0 голосов
/ 09 мая 2019

Одним из решений будет использование таблицы измерений календаря или даты (https://www.mssqltips.com/sqlservertip/4054/creating-a-date-dimension-or-calendar-table-in-sql-server/) в сочетании с представлением для представления диапазона дат для возврата сущности, представляющей каждую дату в диапазоне.

Например:

public class WorkAssignment {
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime Start { get; set; }
    public DateTime End { get; set; }
    public virtual Location Location { get; set; }
    public int LocationId { get; set; }
}

[Table("vwWorkAssignmentByDate")]
public class WorkAssignmentDate 
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime Start { get; set; }
    public DateTime End { get; set; }
    public virtual Location Location { get; set; }
    public int LocationId { get; set; }
    public DateTime Date { get; set; }
}

Обратите внимание, что WorkAssignmentDate не расширяет WorkAssignment.Причина этого заключается в том, что если вы расширяете его, то при прямом запросе WorkAssignment EF будет пытаться выполнить NOT IN для представления, которое одновременно является приемником производительности.а также может вызвать проблемы при попытке загрузить одну строку. (Может быть некоторая форма отображения, которая может избежать этого поведения). Вы можете установить Id в качестве PK для объекта на основе представления, чтобы поддерживать EF счастливым, но это будетне быть уникальным идентификатором строки. (так что никаких обновлений! Не проблема, потому что в любом случае это происходит из представления)

Где vwWorkAssignment - это представление, которое присоединяет WorkAssignment к таблице DateDimension:

SELECT wa.*, dd.Date
FROM dbo.WorkAssignment wa 
INNER JOIN dbo.DateDimension dd 
  ON dd.Date >= wa.StartDate AND dd.Date <= wa.EndDate

Объект WorkAssignmentDate должен рассматриваться как объект только для чтения.то есть рабочее задание, которое вы бы загружали и использовали сущность WorkAssignment по идентификатору.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...