AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 78873729
Accepted
Jefferson
Jefferson
Asked: 2024-08-15 13:21:23 +0800 CST2024-08-15 13:21:23 +0800 CST 2024-08-15 13:21:23 +0800 CST

loop ou um método recursivo não consegue obter os dados

  • 772

Tenho esses dados em uma tabela e estou tentando fazer um loop ou um método recursivo. Preciso obter o resultado com base no uso do ID da reunião. Se eu estiver usando o MeetingID 1, ele retornará 2,3. Se eu fizer o MeetingID 2, obterei 1,3 e se fizer 3, obterei 1,2. Tenho esse método mas preciso ligar muitas vezes e queria saber se existe uma maneira melhor. Acredito que preciso do linq para percorrer a cadeia de reuniões pai/anterior e um que atravesse a cadeia de reuniões secundárias/continuação.

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

EF/Linq:

 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();
c#
  • 3 3 respostas
  • 84 Views

3 respostas

  • Voted
  1. Best Answer
    T N
    2024-08-15T14:29:25+08:002024-08-15T14:29:25+08:00

    Isso pode ser feito em SQL usando dois CTEs recursivos - um que atravessa a cadeia de reunião pai/anterior e outro que atravessa a cadeia de reunião secundária/continuação. (A reunião original é excluída de ambas as listas.) É então apenas uma questão de executar a UNION ALLe (se desejado) a STRING_AGG()para construir a lista final separada por vírgulas.

    Essa lógica pode ser agrupada em uma função definida pelo usuário que pode então ser adicionada ao modelo do Entity Framework e chamada a partir do seu aplicativo.

    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
    

    A lógica acima pressupõe que a cadeia de reuniões é linear com um relacionamento pai/filho 1 para 1. Se os relacionamentos da reunião puderem ser muitos para muitos, a travessia do gráfico seria muito mais complicada.

    Embora lógica semelhante possa ser implementada em C#, não conheço uma maneira de escrever uma instrução LINQ recursiva equivalente que mapeie para uma única execução de consulta SQL. Uma implementação nativa do LINQ provavelmente faria um loop e executaria várias consultas. (Acredito que existam alguns complementos que fornecem suporte limitado a CTE, mas não sei se eles suportam recursão ou seriam adaptados a esta solução. Isso exigiria mais investigação.)

    Resultados (com alguns dados de teste extras):

    ID da reunião Reuniões Relacionadas
    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 nulo

    Veja este db<>fiddle para uma demonstração.

    • 3
  2. rachel
    2024-08-15T19:09:02+08:002024-08-15T19:09:02+08:00

    Honestamente, ainda não tenho certeza do que você quer fazer. e você acabou de editar sua pergunta copiando e colando algumas palavras-chave da primeira resposta recebida.

    Portanto, presumo que a resposta anterior esteja mais ou menos alinhada com o que você está procurando.

    Além disso, você var y = (from m in Meetings where m.MeetingId == MeetingId select new{}).FirstOrDefault()pode ser simplificado usando Meetings.FirstOrDefault(m => m.MeetingId == MeetingId).

    Para escrever um loop while ou método recursivo em Csharp, você pode tentar o código abaixo:

    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);
        }
    }
    
    • 1
  3. T N
    2024-08-16T00:13:51+08:002024-08-16T00:13:51+08:00

    Rascunho, resposta da comunidade

    A seguir está uma possível implementação LINQ da resposta SQL recursiva CTE anterior que usa o recurso LINQ To DB – Common Table Expression (CTE) .

    Este post inicial é um rascunho da tradução do SQL para C# LINQ baseado na documentação, mas não foi testado e pode precisar de correções. Não tenho experiência com isso, então pode precisar de correções ou outras melhorias. Sinta-se à vontade para editar e melhorar esta resposta conforme achar necessário. Se você puder verificar se isso é uma solução funcional, esses comentários poderão ser editados ou removidos conforme apropriado.

    using LinqToDB.Configuration;
    using LinqToDB.Data;
    
    class RelatedMeetingsCTE
    {
        public int MeetingId;
    }
    
    ...
    
    public string GetRelatedMeetings(int meetingId)
    {
        using (var db = ...)
        {
            var priorMeetingsCte = db.GetCte<RelatedMeetingsCTE>(PriorMeetings =>
            {
                return
                    (
                        from m in db.Meetings 
                        where m.ContinuedMeetingId == meetingId
                        select new RelatedMeetingsCTE
                        {
                            MeetingId = m.meetingId
                        }
                    )
                    .Concat
                    (
                        from m in db.Meetings
                        from pm in PriorMeetings
                            .InnerJoin(pm => m.ContinuedMeetingId == pm.MeetingId)
                        select new RelatedMeetingsCTE
                        {
                            MeetingId = m.meetingId
                        }
                    );
            });
    
            var continuedMeetingsCte = db.GetCte<RelatedMeetingsCTE>(ContinuedMeetings =>
            {
                return
                    (
                        from m in db.Meetings 
                        where m.MeetingId == meetingId
                        select new RelatedMeetingsCTE
                        {
                            MeetingId = m.ContinuedMeetingId
                        }
                    )
                    .Concat
                    (
                        from m in db.Meetings
                        from cm in ContinuedMeetings
                            .InnerJoin(cm => m.MeetingId == cm.ContinuedMeetingId)
                        select new RelatedMeetingsCTE
                        {
                            MeetingId = m.ContinuedMeetingId
                        }
                    );
            });
    
            var relatedMeetingsCte =
                (
                    from pm in priorMeetingsCte
                    select new RelatedMeetingsCTE
                    {
                        MeetingId = pm.MeetingId
                    }
                )
                .Concat
                (
                    from cm in continuedMeetingsCte
                    select new RelatedMeetingsCTE
                    {
                        MeetingId = cm.MeetingId
                    }
                )
                .AsCte("RelatedMeetings");
    
            // Or perhaps just...
            //var relatedMeetingsCte =
            //    priorMeetingsCte
            //    .Concat(continuedMeetingsCte)
            //    .AsCte("RelatedMeetings");
    
            var result = string.Join(",", (
                    from rm in relatedMeetingsCte
                    orderby rm.MeetingId
                    select rm.MeetingId.ToString()
                ));
    
            return result;
        }    
    }
    
    • 1

relate perguntas

  • Polly DecorrelatedJitterBackoffV2 - como calcular o tempo máximo necessário para concluir todas as novas tentativas?

  • Wpf. Role o DataGrid dentro do ScrollViewer

  • A pontuação que ganhei na página do jogo com .NET MAUI MVVM não é visível em outras páginas. Como posso manter os dados de pontuação no dispositivo local

  • Use a hierarquia TreeView com HierarchicalDataTemplate de dentro de um DataTemplate

  • Como posso melhorar essa interface de validação no .NET?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle?

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Quando devo usar um std::inplace_vector em vez de um std::vector?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Martin Hope
    Aleksandr Dubinsky Por que a correspondência de padrões com o switch no InetAddress falha com 'não cobre todos os valores de entrada possíveis'? 2024-12-23 06:56:21 +0800 CST
  • Martin Hope
    Phillip Borge Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle? 2024-12-12 20:46:46 +0800 CST
  • Martin Hope
    Oodini Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores? 2024-12-12 06:27:11 +0800 CST
  • Martin Hope
    sleeptightAnsiC `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso? 2024-11-09 07:18:53 +0800 CST
  • Martin Hope
    The Mad Gamer Quando devo usar um std::inplace_vector em vez de um std::vector? 2024-10-29 23:01:00 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST
  • Martin Hope
    MarkB Por que o GCC gera código que executa condicionalmente uma implementação SIMD? 2024-02-17 06:17:14 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve