Цикл или рекурсивный метод не могут получить данные

У меня есть эти данные в одной таблице, и я пытаюсь выполнить цикл или рекурсивный метод. Мне нужно получить базу результатов, используя идентификатор встречи. Если я использую идентификатор встречи 1, он вернет 2,3. Если я выполню MeetingID 2, я получу 1,3, а если сделаю 3, я получу 1,2. У меня есть этот метод, но мне нужно много раз звонить, и я хотел знать, есть ли лучший способ. Я считаю, что мне нужен linq для прохождения цепочки родительских/предыдущих встреч и цепочки дочерних/продолжительных встреч.

MeetingId       ContinuedMeetingId
----------      -------------
1               2
2               3
3               null

ЭФ/Линк:

 var y = (from m in Meetings
          where m.MeetingId == MeetingId
          select new
          {
              ContinuedMeetingsId = db.Meetings
                 .Where(s => s.MeetingId == m.MeetingId)
                 .Select(s => s.ContinuedMeetingId).FirstOrDefault()
          }).FirstOrDefault();

Так в чем именно здесь заключается правило? Выберите MeetingId, который вы не запрашивали? Вам нужно немного подробнее рассказать о том, что вы хотите сделать.

MakePeaceGreatAgain 15.08.2024 07:41

@MakePeaceGreatAgain Я думаю, им нужен такой метод, как GetRelatedMeetings(meetingId).

ProgrammingLlama 15.08.2024 07:43

И почему вы дважды возвращаете встречу? Один раз с объекта Meetings и один раз с db.Meetings? Другими словами: m уже является Meeting, нет необходимости запрашивать его снова у db.Meetings.

MakePeaceGreatAgain 15.08.2024 07:43
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
69
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Это можно сделать в SQL с помощью двух рекурсивных CTE — одного, который пересекает цепочку родительских/предыдущих собраний, и другой, который пересекает цепочку дочерних/продолжительных собраний. (Исходная встреча исключается из обоих списков.) Тогда остается просто нажать UNION ALL и (при желании) STRING_AGG(), чтобы создать окончательный список, разделенный запятыми.

Эту логику можно обернуть в определяемую пользователем функцию, которую затем можно добавить в модель Entity Framework и вызывать из вашего приложения.

CREATE FUNCTION GetRelatedMeetings (@MeetingId INT)
RETURNS VARCHAR(MAX)
AS BEGIN
    DECLARE @RelatedMeetings VARCHAR(MAX);
  
    WITH PriorMeetings AS (
        SELECT M.MeetingId
        FROM Meetings M
        WHERE M.ContinuedMeetingId = @MeetingId
        UNION ALL
        SELECT M.MeetingId
        FROM PriorMeetings PM
        JOIN Meetings M
            ON M.ContinuedMeetingId = PM.MeetingId
    ),
    ContinuedMeetings AS (
        SELECT M.ContinuedMeetingId AS MeetingId
        FROM Meetings M
        WHERE M.MeetingId = @MeetingId
        UNION ALL
        SELECT M.ContinuedMeetingId AS MeetingId
        FROM ContinuedMeetings CM
        JOIN Meetings M
            ON M.MeetingId = CM.MeetingId
    ),
    RelatedMeetings AS (
        SELECT PM.MeetingId
        FROM PriorMeetings PM
        UNION ALL
        SELECT CM.MeetingId
        FROM ContinuedMeetings CM
    )
    SELECT @RelatedMeetings =
        STRING_AGG(RM.MeetingId, ',')
            WITHIN GROUP(ORDER BY RM.MeetingId)
    FROM RelatedMeetings RM;

    RETURN @RelatedMeetings
END

Приведенная выше логика предполагает, что цепочка встреч является линейной с отношениями родитель/потомок 1 к 1. Если бы отношения встреч могли быть «многие ко многим», обход графа был бы гораздо более сложным.

Хотя аналогичная логика может быть реализована в C#, я не знаю способа написать эквивалентный рекурсивный оператор LINQ, который бы отображал выполнение одного запроса SQL. Собственная реализация LINQ, скорее всего, будет зацикливаться и выполнять несколько запросов. (Я считаю, что существуют некоторые надстройки, которые обеспечивают ограниченную поддержку CTE, но я не знаю, поддерживают ли они рекурсию или будут ли они адаптированы к этому решению. Это потребует дополнительного исследования.)

Результаты (с некоторыми дополнительными данными испытаний):

идентификатор встречи ПохожиеВстречи 1 2,3 2 1,3 3 1,2 4 5,6,7 5 4,6,7 6 4,5,7 7 4,5,6 8 нулевой

См. эту db<>fiddle для демонстрации.

linq2db.EntityFrameworkCore поддерживает рекурсивный CTE, и эти три могут быть выражены через LINQ.
Svyatoslav Danyliv 15.08.2024 12:44

Честно говоря, я до сих пор не уверен, что вы хотите сделать. и вы только что отредактировали свой вопрос, скопировав и вставив некоторые ключевые слова из первого полученного ответа.

Поэтому я просто предполагаю, что предыдущий ответ более или менее соответствует тому, что вы ищете.

Также ваш var y = (from m in Meetings where m.MeetingId == MeetingId select new{}).FirstOrDefault() можно упростить, используя Meetings.FirstOrDefault(m => m.MeetingId == MeetingId).

Чтобы написать цикл while или рекурсивный метод в Csharp, вы можете попробовать следующий код:

var meetings = new List<Meeting>
{
    new Meeting {MeetingId = "1", ContinuedMeetingId = "2"},
    new Meeting {MeetingId = "2", ContinuedMeetingId = "3"},
    new Meeting {MeetingId = "3", ContinuedMeetingId = null}
};

var selectedMeetingId = "1";
var nextMeetingIds = new List<string>();
var priorMeetingIds = new List<string>();
var nextMeeting = meetings.FirstOrDefault(m => m.MeetingId == selectedMeetingId);
var priorMeeting = meetings.FirstOrDefault(m => m.ContinuedMeetingId == selectedMeetingId);
while (true)
{
    if (nextMeeting == null && priorMeeting == null)
    {
        break;
    }

    if (nextMeeting != null)
    {
        var nextMeetingId = nextMeeting.ContinuedMeetingId;
        nextMeetingIds.Add(nextMeetingId);
        nextMeeting = meetings.FirstOrDefault(m => m.MeetingId == nextMeetingId);
    }

    if (priorMeeting != null)
    {
        var priorMeetingId = priorMeeting.MeetingId;
        priorMeetingIds.Add(priorMeetingId);
        priorMeeting = meetings.FirstOrDefault(m => m.ContinuedMeetingId == priorMeetingId);
    }
}

Другие вопросы по теме

Похожие вопросы

Нужна помощь в анализе HTML-разметки с помощью CSVHelper через мой .NET API
После перезапуска игры цели не появляются
Таблица данных JQuery – сортировка столбцов не работает в
Как я могу исправить связь многие-ко-многим между двумя объектами, чтобы третья таблица автоматически заполнялась в структуре сущностей и веб-API (С#)
Как я могу зарегистрировать HTTP-ответ с помощью промежуточного программного обеспечения в функциях Azure, выполняющих изолированный процесс .NET 8?
Контекст Testcontainers .NET 8 db, похоже, не обновляется в [Факт], проблема решена, ищет объяснение
Переписать удаление служебной шины Azure
Невозможно вставить явное значение для столбца идентификаторов в таблице «Обсуждаемые продукты», если для параметра IDENTITY_INSERT установлено значение OFF
Сопоставление и удаление подстрок повторяющихся символов, а затем возврат длины самой длинной подстроки
Как отсортировать массив объектов сам по себе на основе свойства указанного объекта?