Search code examples
c#genericsdesign-patternsentity-framework-coreunit-of-work

How can I use `ThenInclude` in generic class in UnitOfWork


I have generic Repository in my project.

I want to use ThenInclude() in Search method of unitofwork

how can i do it?

I use this method but ThenInclude does not work

 public async Task<IEnumerable<TEntity>> FindByConditionAsync(
                                         Expression<Func<TEntity, bool>> filter = null,                                              
                                         Func<IQueryable<TEntity>,IOrderedQueryable<TEntity>> orderBy = null, 
                                         params Expression<Func<TEntity, object>>[] includes)
 {
     IQueryable<TEntity> query = dbSet;
     foreach (var includ in includes)
     {
         query = query.Include(includ);
     }

     if (filter != null)
     {
         query = query.Where(filter);
     }

     if (orderBy != null)
     {
         query = orderBy(query);
     }

     return await query.ToListAsync();
 }

Solution

  • In this case we need to change params Expression<Func<TEntity, object>>[] includes to Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> include = null. IIncludableQueryable<> now permits us to use ThenInclude() and some changes make this method better.

    SampleCode :

     /// <summary>
     /// Gets the IEnumerable entities based on a conditionally, orderby delegate and include delegate. This method default no-tracking query.
     /// </summary>
     /// <param name="selector">Mannage type of IEnumerable class that you want to return it</param>
     /// <param name="filter">Set condition for filter</param>
     /// <param name="orderBy">For set order of elements</param>
     /// <param name="include">Set include and thenInclude with this</param>
     /// <param name="disableTracking">disable tracking if is true take query AsNoTracking default is true</param>
     /// <typeparam name="TResult">the type of IEnumerable that you want return</typeparam>
     /// <returns>Return IEnumerable TResult type</returns>
     public async Task<IEnumerable<TResult>?> FindByConditionAsync<TResult>(Expression<Func<TEntity, TResult>> selector,
                                                  Expression<Func<TEntity, bool>> filter = null,
                                                  Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
                                                  Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> include = null,
                                                  bool disableTracking = true)
     {
         IQueryable<TEntity> query = dbSet;
        
         query = disableTracking ? query.AsNoTracking() : query.AsTracking();
    
         if (include != null) query = include(query);
    
         if (filter != null) query = query.Where(filter);
    
         if (orderBy != null) _ = orderBy(query);
    
         return (query.Count() != 0) ? await query.Select(selector).ToListAsync() : null;
     }
    

    Example:

    var q = await conector.RepositoryBase<TEntity>().FindByConditionAsync<TResult>(
        s => new TResult(){ prop1 = s.prop1 , etc.. },
        f => //Condition,
        o => o.OrderBy(i => i.prop),
        i => i.Include(i => i.prop1).ThenInclude(t => t.innerprop1)
              .Include(i => i.prop2).ThenInclude(t => t.innerprop2)
    );