Why DbSet doesn't implement EnumerableAsync

async-await c#-5.0 entity-framework entity-framework-6 ienumerable

Question

In Entity framework 6.1.1 an IDbSet represents the collection of entities which can be queried from the database and its concrete implementation is DbSet as described in

DbSet

How come this interface or its concrete implementation doesn't contain any definition for ToEnumerableAsync or AsEnumerableAsync but ToListAsync,ToArrayAsync,ToDictionaryAsync?

To give you an idea of why I came across this question I have the following piece of code which I wanted to make async:

public IQueryable<TEntity> GetQuery<TEntity>() where TEntity : class
{
    string entityName = GetEntityName<TEntity>();
    return ((IObjectContextAdapter)DbContext).ObjectContext.CreateQuery<TEntity>(entityName);
}


public IEnumerable<TEntity> Get<TEntity, TOrderBy>(Expression<Func<TEntity, TOrderBy>> orderBy, int pageIndex, int pageSize, SortOrder sortOrder = SortOrder.Ascending) where TEntity : class
{
    if (sortOrder == SortOrder.Ascending)
    {
        return GetQuery<TEntity>().OrderBy(orderBy).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsEnumerable();
    }
    return
        GetQuery<TEntity>()
            .OrderByDescending(orderBy)
            .Skip((pageIndex - 1) * pageSize)
            .Take(pageSize)
            .AsEnumerable();
}

The only implementation which comes to my mind is as follows:

public async Task<IEnumerable<TEntity>> GetAsync<TEntity, TOrderBy>(Expression<Func<TEntity, TOrderBy>> orderBy, int pageIndex, int pageSize, SortOrder sortOrder = SortOrder.Ascending) where TEntity : class
{
    if (sortOrder == SortOrder.Ascending)
    {
        return await GetQuery<TEntity>().OrderBy(orderBy).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync();
    }
    return
        await GetQuery<TEntity>()
            .OrderByDescending(orderBy)
            .Skip((pageIndex - 1) * pageSize)
            .Take(pageSize)
            .ToListAsync();
}

Is this the correct approach in regards to making a method asynchronous?

Above methods belong to the generic repository implemented in the following links: Entity Framework POCO, Repository and Specification Pattern To dig deeper you can have a look at the originating blog: Entity Framework POCO, Repository and Specification Pattern

1
10
8/8/2014 2:18:54 PM

Accepted Answer

The design of IEnumerable doesn't allow it to be used with async/await. IEnumerator<T>.MoveNext() cannot return any Task object that the caller can await, because it has got a fixed return type of bool.

The async-aware version of IEnumerable is IDbAsyncEnumerable, and that's already implemented by DbQuery<T>, from which DbSet<T> derives, so no AsDbAsyncEnumerable() extension method is necessary for that to work.

Your Get version, IMO, does not need an Async version. It already doesn't block, because it doesn't do anything. Only when the caller starts using the returned enumerable, will the database be queried. I'd just change the return type to DbQuery<TEntity>. (This requires a cast, but should already be the concrete type that gets returned.) The caller can then decide whether to use synchronous methods, or asynchronous methods.

(Actually, on closer inspection, I see that although your question is about DbSet<T>, you're actually using the backing ObjectContext instead of the DbContext. This will likely give you ObjectQuery<T> queryables rather than DbQuery<T> queryables, for which the answer will be different. You'll make things easier on yourself if you stop using the ObjectContext except when you really need to.)

9
8/8/2014 1:59:23 PM

Popular Answer

Because you can't have a Enumerable, that class is static. You can have a IEnumerable, but List, Array, and Dictionaries all implement it so what would your underlying type be in your ToEnumerableAsync()?

You can easily do

IEnumerable<TEntity> result = await yourDbSet.ToListAsync();


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow