1 Вопрос: Как я могу «расширить» результаты IQueryable на основе диапазона значений?

вопрос создан в Wed, May 8, 2019 12:00 AM

Я пытаюсь определить способ использования 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, предпочтительно используя методы интерфейса. Важно выполнить «расширение» в запросе (сделать ответственной БД). Полный набор данных и ссылки на сущности большой , и я не хочу реализовываться с использованием операторов .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.

    
0
1 ответ                              1                         

Одним из решений будет использование таблицы измерений календаря или даты ( 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 по идентификатору.

    
0
2019-05-09 00: 06: 28Z
источник размещен Вот