Optimize operation with lambda

Asked

Viewed 510 times

2

I have the following classes:

public class Pedidos_Itens
{
    public int ID { get; set; }
    public int Qtde { get; set; }
    public Pedidos _Pedido { get; set; }
    public int Pedido { get; set; }
    public Loja_Produtos _Produto;
    public int Produto { get; set; }
}

And

public class Loja_Produtos
{
    public int ID { get; set; }
    public string Nome { get; set; }
 }

And

public class Pedidos
{
    public int ID { get; set; }
    public DateTime Data { get; set; }
    public decimal Valortotal { get; set; }
}

But the bank doesn’t have a foreign key and I can’t modify the bank’s NADA. So I cannot use include (I believe it is because of the absence of the foreign key). So I did the following:

    public IEnumerable<Pedidos_Itens> ListarTodos()
    {
        var itens = contexto.PedidoItem.ToList();
        var list = new List<Pedidos_Itens>();
        foreach (var i in itens)
        {
            i._Produto = contexto.Produto.First(x => x.ID == i.Produto);
            i._Pedido = contexto.Pedido.First(x => x.ID == i.Pedido);
        }
        return list;
    }

But I believe there’s a more efficient way to do the same.

2 answers

1

I believe this will meet.

var itens = contexto.PedidoItem.Select(pi => new
{
    ID = pi.ID,
    Qtde = pi.Qtde,
    Produto = pi.Produto,
    _Produto = contexto.Produto.FirstOrDefault(pr => pr.ID == pi.Produto),
    Pedido = pi.Pedido,
    _Pedido = contexto.Pedido.FirstOrDefault(pe => pe.ID == pi.Pedido)
}).ToList();
  • The following error occurred: An unhandled Exception of type 'System.Notsupportedexception' occurred in Entityframework.SqlServer.dll Additional information: The Entity or Complex type 'Repositorioef.Pedidos_items' cannot be constructed in a LINQ to Entities query.

  • @Diegozanardo try to get the guy Pedidos_Itens that I am giving new, and make a Dynamic Object. If this works, the performance will be as optimized as.

  • I think the problem is that there are products within Pedidoitem, which no longer exist in the product table.

  • @Diegozanardo try then use .FirstOrDefault instead of .First

1


Example:

As you yourself reported that there is no key, then an Inner Join has been made in these tables and the result will be a list.

var resposta = contexto.Pedidos_Itens
                .Join(contexto.Loja_Produtos, pi => pi.Produto, l => l.ID, (pi, l) => new { pi, l })
                .Join(contexto.Pedidos, p => p.pi.Pedido, pe => pe.ID, (p, pe) => new { p, pe })
                .Select(s => new
                {
                    Loja_Produtos_ID = s.p.l.ID,
                    Loja_Produtos_NOME = s.p.l.Nome,
                    Pedidos_Itens_ID = s.p.pi.ID,
                    Pedidos_Itens_QTDE = s.p.pi.Qtde,
                    Pedidos_ID = s.pe.ID,
                    Pedidos_DATA = s.pe.Data, 
                    Pedidos_VALORTOTAL = s.pe.Valortotal
                });

The consultation is certainly slow, by the reported lack of keys and relationships and lack of indexing, but, works in a certain way until favorable.

With Linq to Objects:

public IEnumerable<Pedidos_Itens> ListarTodos()
{
    contexto contexto = new ConsoleApplication1.contexto();
    var resposta = contexto.Pedidos_Itens
        .Join(contexto.Loja_Produtos, pi => pi.Produto, l => l.ID, (pi, l) => new { pi, l })
        .Join(contexto.Pedidos, p => p.pi.Pedido, pe => pe.ID, (p, pe) => new { p, pe })
        .Select(s => new
        {
            Loja_Produtos_ID = s.p.l.ID,
            Loja_Produtos_NOME = s.p.l.Nome,
            Pedidos_Itens_ID = s.p.pi.ID,
            Pedidos_Itens_QTDE = s.p.pi.Qtde,
            Pedidos_ID = s.pe.ID,
            Pedidos_DATA = s.pe.Data,
            Pedidos_VALORTOTAL = s.pe.Valortotal
        });

    IList<Pedidos_Itens> ListaPedidosItens = new List<Pedidos_Itens>();
    foreach (var resp in resposta)
    {
        ListaPedidosItens.Add(new Pedidos_Itens()
        {
            ID = resp.Pedidos_Itens_ID,
            Qtde = resp.Pedidos_Itens_QTDE,
            _Pedido = new Pedidos() { ID = resp.Pedidos_ID, Data = resp.Pedidos_DATA, Valortotal = resp.Pedidos_VALORTOTAL },
            _Produto = new Loja_Produtos() { ID = resp.Loja_Produtos_ID, Nome = resp.Loja_Produtos_NOME }
        });
    }
    return ListaPedidosItens.AsEnumerable();
}

Obs: It’s not very usual to do this, but, with Linq to Objects, you will simulate the same thing that if you had keys and relationships, not very performative, but functional

Why better?

Will perform a single SQL with Inner Join and then in memory the data will be worked with Linq to Objects.

  • But how do I make this a list of the Requested class_items?

  • Let me ask on top? What’s the point ?

  • Why is part of the public Enumerable<Requested method_items> Listed(){} .

  • Because, part of it did not offer me a proper response, but, @Diegozanardo, I did an issue putting the way closer to ideal.

  • 1

    This method is part of the repository layer and it incorporates an interface that ensures that it will return a method with this signature.

  • Understood @Diegozanardo, inclusive edite a resposta!

Show 1 more comment

Browser other questions tagged

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