How to structure query functions in services
I have the following function in my service layer csharp:
PS: A category can have List<Item>
Sometimes I need
GetCategories()
to just be the Category
without any navigation properties included.
But also sometimes I need GetCategories()
to also include the Items
navigation property...
I'm thinking of having two functions with two separate dtos (one has only the category, the other one has the category + the items).
But I was wondering if there's a better way to do this16 Replies
Definitely sounds like a job for two different methods, selecting into two different DTOs
you can use IIncludableQueryable
https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.query.iincludablequeryable-2?view=efcore-8.0
IIncludableQueryable Interface (Microsoft.EntityFrameworkCore.Query)
Supports queryable Include/ThenInclude chaining operators.
but you can use it only with ef core 🙂
Yeah I know about
Include
the question is how to structure it
I could do a public async Task<List<Category>> GetCategories(bool includeItems)
I don't think I'd like to make the consumer choose the includes...
public async Task<IQueryable<T>> GetListAsync(Expression<Func<T, bool>>? predicate = null, Func<IQueryable<T>, IOrderedQueryable<T>>? orderBy = null, Func<IQueryable<T>, IIncludableQueryable<T, object>>? include = null, bool enableTracking = true, CancellationToken cancellationToken = default)
{
IQueryable<T> queryable = Table.AsQueryable();
if (!enableTracking) queryable = queryable.AsNoTracking();
if (include != null) queryable = include(queryable);
if (predicate != null) queryable = queryable.Where(predicate);
if (orderBy != null)
return await Task.FromResult(orderBy(queryable));
return await Task.FromResult(queryable);
}
Otherwise why bother having a service layer for the query? you could straight up get the context at the controller or in the desktop gui function and do everything there
I appreciate your input but I'm a bit sceptical of making the consumer of the function be mindful about Includes
You should define this in the data access or persistence layer and use it only in the service layer.
What do you see as a problem?
The only problem is that you cannot use it in Dapper or a similar orm other than EF Core.
That's how I'd do it
sorry, I misunderstood the question
Well, ideally I'd just inject the context into the service instead of using the factory, but I guess you're using it in Blazor or some such
I think factory is more performant
I misunderstood the problem. Sorry, I just realized. I think you want to call the same method in two different ways in two different services in the Service Layer, is that correct?
Yep, blazor hybrid