2
\$\begingroup\$

I'm working with a third part service of my client that is providing me a list of products and services, which is a little bit of a mess.

The list will return all of the services for the product but the product repeats itself, for example:

The product A has the service A and the product A also has the service B so, when i receive the list i will get two products A with services A and B

What i need to do is to group all of the products to get only one with all of it's services and i have done so but i'm worried about performance because i think my solution isn't the 'best' one:

var productsNormalized = products.Data.AsEnumerable().Select(x => new ProdutoSSO
{
    CodigoServico = int.Parse(string.IsNullOrEmpty(x["CodigoServico"].ToString()) ? "0" : x["CodigoServico"].ToString()),
    CodigoPeca = int.Parse(string.IsNullOrEmpty(x["CodigoPeca"].ToString()) ? "0" : x["CodigoPeca"].ToString()),
    CodigoFamilia = int.Parse(string.IsNullOrEmpty(x["CodigoFamilia"].ToString()) ? "0" : x["CodigoFamilia"].ToString()),
    Familia = x["Familia"].ToString(),
    Servico = x["Servico"].ToString(),
    Peca = x["Peca"].ToString(),
    Hash = x["Hash"].ToString(),
    Valor = decimal.Parse(string.IsNullOrEmpty(x["Valor"].ToString()) ? "0" : x["Valor"].ToString())
})
.GroupBy(x => new { x.CodigoPeca, x.CodigoFamilia, x.Familia, x.Peca })
.Select(x => new ProdutoGroup
{
    Produto = new Produto
    {
        CodigoPeca = x.Key.CodigoPeca,
        CodigoFamilia = x.Key.CodigoFamilia,
        Familia = x.Key.Familia,
        Peca = x.Key.Peca
    },
    Servicos = x.Select(y => new ProdutoServico
    {
        CodigoServico = y.CodigoServico,
        Hash = y.Hash,
        Servico = y.Servico,
        Valor = y.Valor
    }).ToList()
});

Is there a better way to achieve this or this is as good as it gets?

\$\endgroup\$
2
  • 3
    \$\begingroup\$ If it's working correctly, and working for acceptable time, then you don't have reasons to change it. \$\endgroup\$
    – tym32167
    Commented Jul 7, 2017 at 16:13
  • \$\begingroup\$ @tym32167 i can't fully test it for now because i don't have the full database. But as i was told we are going to work with something close to 3k requests per day and 400 products. \$\endgroup\$
    – Ariel
    Commented Jul 10, 2017 at 14:08

1 Answer 1

1
\$\begingroup\$

There are some improvemants possible but they are rather of technical nature then about performance as I don't think you can do much about it until you have measured it either with benchmarks or a profiler.


products.Data.AsEnumerable()

This looks like you are working with a DataTable, aren't you? If the data comes from a database then you should group it on the server.


CodigoServico = int.Parse(string.IsNullOrEmpty(x["CodigoServico"].ToString()) ? "0" : x["CodigoServico"].ToString()),
CodigoPeca = int.Parse(string.IsNullOrEmpty(x["CodigoPeca"].ToString()) ? "0" : x["CodigoPeca"].ToString()),
CodigoFamilia = int.Parse(string.IsNullOrEmpty(x["CodigoFamilia"].ToString()) ? "0" : x["CodigoFamilia"].ToString()),

You should create a helper extension or function for such lines, it's pretty ugly to repeat it so many times. Even two times is already too many.


.GroupBy(x => new { x.CodigoPeca, x.CodigoFamilia, x.Familia, x.Peca })

You are grouping by the same properties as the object has that you create in the next step:

Produto = new Produto
{
  CodigoPeca = x.Key.CodigoPeca,
  CodigoFamilia = x.Key.CodigoFamilia,
  Familia = x.Key.Familia,
  Peca = x.Key.Peca
},

Instead of doing this twice you should implement the IEquatable<Produto> interface on this object and use this instance as a key so that you only have a single new.


Servicos = x.Select(y => new ProdutoServico
{
  CodigoServico = y.CodigoServico,
  Hash = y.Hash,
  Servico = y.Servico,
  Valor = y.Valor
}

You can replace this with Servicos = x if you use another overload of GroupBy and project each item right away.

\$\endgroup\$
2
  • \$\begingroup\$ I have managed to implement most of your tips but i couldn't find my way to implement the IEquatable and how to use it on the Select. Could you please provide a small example with the GroupBy overload ? I'm quite new to C#. Thanks. \$\endgroup\$
    – Ariel
    Commented Jul 10, 2017 at 14:03
  • 1
    \$\begingroup\$ @Terkhos I completely forgot your question about the IEquatable, sorry ;-] I'll answer with a link because I think this a nice explanation how to do it correctly. \$\endgroup\$
    – t3chb0t
    Commented Jul 25, 2017 at 14:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.