Проблема понимания структуры запросов Linq, когда она включает фильтрацию, выравнивание и группирование - PullRequest
0 голосов
/ 04 декабря 2018

Я сталкиваюсь с множеством проблем при попытке извлечь данные из этой модели данных с помощью LinqToEntities.

Я работаю с EF Core 2.1 и Linq над базой данных SQL Server.

В основном мне нужно показывать события в еженедельном календаре, но структура данных довольно сложная.У событий может быть несколько EventDate (каждая дата - это один день с начальным и конечным часами), и в каждый день много разных контактов участвуют иногда в другое время, чем общее в EventDate.

Мне нужно отфильтроватьих по недельным периодам (Startdate, EndDate), а иногда и по списку задействованных контактов.

Основная проблема заключается в том, что мне нужно извлечь список отдельных объектов (отфильтрованных по запросу) по одному для каждой EventDate, носо всеми переопределениями, сгруппированными в нем, и со списком контактов для каждой группы переопределений, например, такой пример структуры:

EventID,
EventName, 
//...Other Data from Events
FromDateTime, //Taken from the EventDate Table
ToDateTime, //Taken from the EventDate Table
//...Other Data from EventDates
Overrides:[
    //Taken from the EventDateContact Table
    {
        OverrideFromHour, 
        OverrideToHour 
        Contacts [contactid, contactid, ...] 
    },
    {
        OverrideFromHour,
        OverrideToHour
        Contacts [contactid, contactid, ...]
    }
]

У меня все еще есть проблемы с пониманием LinqToEntities для очень сложных запросов.

В приложениях, отличных от EF / Linq, я бы выполнил объединение таблиц, а затем по необходимости повторил бы группировку результатов вручную, но мне интересно, есть ли способ сделать это напрямую, используя LinqToEntities или смешивая его с просыпающимися в памяти LinqToObjectsпосле одного или другого начальногозапросов.

Я пробовал разные объединения и группировки, но я не могу понять, как это работает!

Вот модель данных:

public class Event {

    public Event()
    {
        EventDates = new HashSet<EventDate>();
        EventDatesContacts = new HashSet<EventDatesContact>();
    }

    public int ID { get; set; }

    public string Name { get; set; }

    ...other data

    public virtual ICollection<EventDate> EventDates { get; set; }

    public virtual ICollection<EventDatesContact> EventDatesContacts { get; set; }
}


public class EventDate {

    public EventDate()
    {
        EventDatesContacts = new HashSet<EventDatesContact>();
    }

    public int ID { get; set; }

    public int EventID { get; set; }

    //The Date part remain the same between From and To. 
    //Only the Hour can change.
    public DateTime FromDateTime { get; set; }

    public DateTime ToDateTime { get; set; }

    //...other data

    public virtual Event Event { get; set; }

    public virtual ICollection<EventDatesContact> EventDatesContacts { get; set; }

}

public class EventDatesContact {

    public int ID { get; set; }

    public int EventID { get; set; }

    public int ContactID { get; set; }

    public int EventDateID { get; set; }

    //If not null these overrides the corresponding DateTime in the EventDate
    //The Date part remain the same between From and To and also the same as the linked EventDate. 
    //Only the Hour can change.
    public DateTime? OverrideFromTime { get; set; }

    public DateTime? OverrideToTime { get; set; }

    //...other data

    public virtual Contact Contact { get; set; }

    public virtual EventDate EventDate { get; set; }

    public virtual Event Event { get; set; }

}

Спасибозаранее за любую поддержку!

1 Ответ

0 голосов
/ 05 декабря 2018

Я не очень часто использую EF, но вам не нужно присоединяться к EF.Вы должны иметь возможность просто использовать свойства навигации, но вам нужно будет группировать, поскольку вы консолидируете EventDate.EventDatesContacts в своем результате.Вот моя попытка:

var results = db.Events
                .Include(e => e.EventDates).ThenInclude(ed => ed.EventDatesContacts)
                .SelectMany(e => e.EventDates.Select(ed => new Result {
                    EventID = e.ID,
                    EventName = e.Name,
                    FromDateTime = ed.FromDateTime,
                    ToDateTime = ed.ToDateTime,
                    Overrides = ed.EventDatesContacts.GroupBy(edc => new {
                            FromTime = edc.OverrideFromTime == null ? ed.FromDateTime : edc.OverrideFromTime.Value,
                            ToTime = edc.OverrideToTime == null ? ed.ToDateTime : edc.OverrideToTime.Value
                        },
                        edc => edc.ContactID
                        )
                        .Select(edcg => new EventOverride {
                            OverrideFromHour = edcg.Key.FromTime,
                            OverrideToHour = edcg.Key.ToTime,
                            ContactIDs = edcg.ToList()
                        })
                        .ToList()
                }));

Насколько я понимаю, вам, возможно, не понадобится Include, если включена активная загрузка.

...