Most of you know that ToList(), ToArray() use a lot of memory because they recreate the array after N element. I need to get all rows from table and I wrote smth like this
ToArray(_dbContext.MyTable.Count(), _dbContext.MyTable.Select(x => ...})
T[] ToArray<T>(int arraySize, IEnumerable<T> list)
{
var result = new T[arraySize];
byte tempIndex = 0;
foreach (var item in list)
{
result[tempIndex] = item;
tempIndex ;
}
return result;
}
This code uses about 10% less memory than simple
_dbContext.MyTable.Select(x => ...}).ToList() \ ToArray()
Does EF have something similar to my code?
CodePudding user response:
You are using less memory, but for sure, this operation will take more time running if the table is big and/or your database is non local.
You are performing two queries in the database, something like:
-
select count(*) from MyTable
-
select * from MyTable
EF uses a single query to achieve the same functionality. I think 10% memory is a very small price to pay for the better performance. Because of that, EF does not have this behavior.
CodePudding user response:
EF does not have this, but neither is the proposed method a good solution.
The proposed solution is not good because it runs two queries on the database, and that extra database call will tend to outweigh the extra RAM use. But let's say you know the size of the results (maybe because of pagination) and can skip the extra database query. Even then, this is still slower than it needs to be.
Instead, the way to optimize this is by recognizing that neither ToArray()
or ToList()
are necessary in the first place in most situations. Learn to work with the resulting IEnumerable
, IQueryable
, IAsyncEnumerable
, etc directly. You can already use them for databinding or in a foreach
loop to create whatever result you need; there's rarely a real need to call ToArray()
at all.
Most of the time when you seem to need ToList()
or ToArray()
, it's because you're calling a method asking for an argument of that type. These methods should also be updated to instead ask for IEnumerable
or IAsyncEnumerable
. If you can push this all the way down the chain, the memory efficiency of your code can be increased dramatically, because the full result set is never loaded into memory; you only ever have one record in memory at a time.