Entityframework . Asenumerable() or . Tolist()?

Asked

Viewed 621 times

4

In one of the projects I picked up I saw the following code, which implements a data listing method of a given entity, but this listing is used only for reading:

/// <summary>
/// Listar todas entidades
/// </summary>
/// <returns></returns>
public IList<T> ListarTodos()
{
    return ctxContexto.Set<T>().ToList();
}

The method works perfectly, my doubt is about performance and good programming practices with Entityframework. A while ago I saw a question here at Sopt that talked about difference between Ienumerable, Iqueryable and Ilist.

Based on the above-mentioned question, I thought "If my method returns a List<T> I will be giving the person who calls the method the possibility to insert or remove items from the list, "which is not correct, since my list is read-only.

List<Cliente> lista = new Servico<Cliente>().ListarTodos();
lista.RemoveAt(0)
lista.Add(new Cliente());

I changed the method return to Ienumerable as below:

/// <summary>
/// Listar todas entidades
/// </summary>
/// <returns></returns>
public IEnumerable<T> ListarTodos()
{
    return ctxContexto.Set<T>().AsEnumerable();
}

The above code also worked, again every time I call the Listed method, if I perform more than one check with the list item in the same code context:

List<Cliente> lista = new Servico<Cliente>().ListarTodos();
int count = lista .Count();
Console.WriteLine(count);
Console.WriteLine(lista .Any());

The message is presented by Resharper.

Possible Multiple enumeration of Ienumerable

This has also been dealt with in a question here from Sopt and I understood why of the same, my doubts are:

What is the best approach in this case?

Some of them will bring me some performance benefit?

2 answers

3


What is the best approach in this case?

Continue to use List<>, which is the resolution in memory of an enumeration. An enumeration may be a function or method whose performance is worse.

If you want the list to be read-only (which I don’t understand, because a list can be changed within the flow of a request), you should use AsReadOnly():

/// <summary>
/// Listar todas entidades
/// </summary>
/// <returns></returns>
public IReadOnlyCollection<T> ListarTodos()
{
    return ctxContexto.Set<T>().ToList().AsReadOnly();
}

Some of them will bring me some performance benefit?

The way you’re using it, no. Using repository over repository, in addition to unjustified, brings unnecessary performance penalties.

  • "(which I don’t understand, because a list can be changed within the flow of a request)". I may not have expressed myself well, but the context of my application requires this piece to be read-only. In my case it is a rule of my business.

  • Then use a read-only list. If List<> can be changed, it is not the data structure you need.

  • I disagree with my friend @cigano-Morrison-Mendez, because List is a Class where implements all these interfaces: Ilist<T>, Icollection<T>, Ienumerable<T>, Ienumerable, Ilist, Icollection, Ireadonlylist<T>, Ireadonlycollection<T>

-1

List is a Class where all these interfaces are implemented:

Ilist, Icollection, Ienumerable, Ienumerable, Ilist, Icollection, Ireadonlylist, Ireadonlycollection

  1. For iteration only 1 time with the result, use the Ienumerable or Ireadonlycollection interface
  2. For more than one iteration, convert your enumerable to list: .ToList() at the beginning of the scope of the method where it is called the method with Ienumerable return!

I hope I’ve helped!

  • This answer is incorrect. The fact of List implement IReadOnlyList is precisely so that the method AsReadOnly() be viable. Also, the use of repository on top of EF brings clear performance penalties, by forcing TABLE SCANs unnecessary in memory.

  • @Ciganomorrisonmendez what I disagreed with his reply was: "Continue to use List<>, which is the resolution in memory of an enumeration. An enumeration can be a function or method, whose performance is worse." When List implements Ienumerable, since when will a Ienumerable return perform worse than an entire class that implements multiple interfaces? I may be wrong, but the principle of logic does not allow me to understand this! If you have any explanation to convince me otherwise I would appreciate!

  • IEnumerable<T> calls for the implementation of GetEnumerator(), which is a method, not a memory class. The path for reading the elements will be at least, O(n).

  • 1

    In addition, the enumeration behavior in the Entity Framework makes, in solving this enumeration, the execution of an SQL sentence (in the conversion of IQueryable, of a DbSet, in IEnumerable, which also worsens performance). Best practice, for the author of the question, would be the method to be public IQueryable<T> ListarTodos(), and explain here why the practice is simply useless.

  • Now yes... about Iqueryable is not even discussed, because effectively did not execute SQL! But between List and Ienumerable, I stick with Ienumerable as return of lists and not enitdades!

Browser other questions tagged

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