Consultation Group by Linq

Asked

Viewed 432 times

-2

It would be possible to consult the table below in a single query?

It would be a group by query using Context with Entity Framework where:

The 3 customers who spent the most on services per month in the current year according to table :

inserir a descrição da imagem aqui

The tables would be:

-client table: Name; Neighborhood; City; State;

namespace ServicosPrestados.Models
{
    public class Cliente
    {
        public int Id { get; set; }

        public string Nome { get; set; }

        public string Bairro { get; set; }

        public string Cidade { get; set; }

        public string Estado { get; set; }
    }
}

-Table of services provided: Description of service Call date Service value

namespace ServicosPrestados.Models.Entidades
{
    public class Servico
    {
        public int Id { get; set; }
        public string Descricao { get; set; }
        public DateTime Data { get; set; }
        public decimal Valor { get; set; }
        public virtual Cliente Cliente { get; set; }
        public int IdCliente { get; set; }

    }
}

mapping:

using ServicosPrestados.Models.Entidades;
using System.Data.Entity.ModelConfiguration;

namespace ServicosPrestados.Models.Mapeamento
{
    public class ServicoMapeamento : EntityTypeConfiguration<Servico>
    {
        public ServicoMapeamento()
        {
            ToTable("SERVICO");

            HasKey(x => x.Id);

            Property(x => x.IdCliente)
               .HasColumnName("ID_CLIENTE")
               .HasColumnType("int")
               .IsRequired();

            Property(x => x.Descricao)
               .HasColumnName("DESCRICAO")
               .HasColumnType("varchar")
               .HasMaxLength(100)
               .IsRequired();

            Property(x => x.Data)
               .HasColumnName("DATA")
               .HasColumnType("datetime")
               .IsRequired();

            Property(x => x.Valor)
              .HasColumnName("VALOR")
              .HasColumnType("decimal")
              .IsRequired();

            HasRequired(m => m.Cliente).WithMany().HasForeignKey(m => m.IdCliente);
        }
    }
}
  • Yes, it is possible. Give more details: is it EF, is it another Provider or do you want to do in memory? What are the sets that contain this data called? Service records are directly linked to Cliente? If yes, by what property? Without this it is even possible to answer, but it will become something either very abstract or very long

  • is EF . is simple foreign key Client -> Service (id) using virtual.

  • It would be nice to [Dit] your question and add this information.

  • Look, how could you answer without seeing the context class and the models? Post this too, but please post only the part needed to answer the question.

  • see if they need anything else

1 answer

1


There’s not much mystery, just use the method GroupBy.

Note that I created an instance of CultureInfo to have control over the name of the months, in your case you need to see how the application handles this.

var cultura = new CultureInfo("pt-BR"); 
contexto.Servicos.GroupBy(serv => serv.Data.Month)
                  .Select(gp => new
                         {
                             Mes = cultura.DateTimeFormat.GetMonthName(gp.Key),
                             Servicos = gp.GroupBy(s => s.Cliente)
                                          .Select(g => new
                                                       { 
                                                           Cliente = g.Key, 
                                                           Valor = g.Sum(x => x.Valor)  
                                                       })
                          });

If you want to take a test, here’s a functional code

using System;
using System.Linq;
using System.Globalization;
using System.Collections.Generic;

class MainClass 
{
    static Cliente[] clientes = new [] 
    {
        new Cliente { Nome = "1 - Abel" },
        new Cliente { Nome = "2 - Bruna" },
        new Cliente { Nome = "3 - Carlos" },
        new Cliente { Nome = "4 - Dara" },
        new Cliente { Nome = "8 - Helena" }
    };

    static IEnumerable<Servico> servicos = new [] 
    {
        new Servico
        {
            Data = new DateTime(2019, 01, 02),
            Valor = 100,
            Cliente = clientes[0]
        },
        new Servico
        {
            Data = new DateTime(2019, 01, 13),
            Valor = 200,
            Cliente = clientes[0]
        },
        new Servico
        {
            Data = new DateTime(2019, 01, 13),
            Valor = 123,
            Cliente = clientes[1]
        },
        new Servico
        {
            Data = new DateTime(2019, 01, 13),
            Valor = 324,
            Cliente = clientes[1]
        },
        new Servico
        {
            Data = new DateTime(2019, 01, 13),
            Valor = 543,
            Cliente = clientes[2]
        },
        new Servico
        {
            Data = new DateTime(2019, 02, 21),
            Valor = 421,
            Cliente = clientes[2]
        },
        new Servico
        {
            Data = new DateTime(2019, 02, 21),
            Valor = 421,
            Cliente = clientes[3]
        },
        new Servico
        {
            Data = new DateTime(2019, 02, 21),
            Valor = 421,
            Cliente = clientes[4]
        }
    };

    public static void Main (string[] args) 
    {
        var cultura = new CultureInfo("pt-BR");
        var resultado = servicos
                            .GroupBy(serv => serv.Data.Month)
                            .Select(gp => new
                                   {
                                       Mes = cultura.DateTimeFormat.GetMonthName(gp.Key),
                                       Servicos = gp.GroupBy(s => s.Cliente)
                                                    .Select(g => new 
                                                                 { 
                                                                   Cliente = g.Key, 
                                                                   Valor = g.Sum(x => x.Valor)
                                                                 })
                                   });

        foreach(var item in resultado)
        {
             Console.WriteLine(item.Mes);
             foreach(var servico in item.Servicos)
             {
                Console.WriteLine($"\t\t{servico.Cliente.Nome} - {servico.Valor}");
             }
        }

    }
}

public class Servico
{
    public DateTime Data { get; set; }
    public decimal Valor { get; set; }
    public Cliente Cliente { get; set; }
    public int IdCliente { get; set; }
}

public class Cliente
{
    public string Nome { get; set; }
}

See working on Repl.it

  • legal. and in the following months that has no sale, how could I do without gambiarra ? because I thought to create a month/year array and make a Join in the Linq.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.