question

RK-2295 avatar image
0 Votes"
RK-2295 asked cooldadtx commented

Is it a good practive to return IQueryable from repositoy in .net core api

Hi All,

I am writing an API with Clean Architecture in .net core with CQRS and MediatR.
My question is "Is it a good practice of returning IQueryable from repository?"
As I want to use GraphQL to provide more flexibility to UI to query data.
Please help me to understand the better approach.

Best Regards,

RK

dotnet-aspnet-core-webapi
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

cooldadtx avatar image
0 Votes"
cooldadtx answered cooldadtx commented

IQueryable is a leaky interface so really you should never expose it from anything you plan to test. The problem is it is pretty much impossible to properly test as every implementation is different. Even MS hasn't fully implemented it in the largest implementation they have (EF). This is perhaps the greatest pushback against OData (which people tend to need it for). Problems with it:

  • No way to properly test it as it is large and complex

  • Every implementation is different and what is supported in one (say in-memory) is not necessarily supported in another (EF)

  • No way to evaluate how the data is being queried so you can potentially build better structures and/or datasets to support the app needs

  • Possible to build queries that can easily tank your DB performance

Outside of OData I don't know anyone who recommends every exposing this interface given the issues it is has. It is an internal interface only. Even OData folks warn to lock down this interface so bad queries aren't written but I've never seen an example of how you would do that.

Since you plan to use GraphQL that means you are going to be exposing your query/mutators explicitly so you shouldn't need IQueryable anyway. It depends upon your approach though. Here's a starter article that may help you. Of course the challenge will be building efficient queries that don't pull back all the data and then filter and that could be a challenge.

Personally I have yet to find a good use case for GraphQL/OData that warrants the complexity it adds. There are definite plusses but at the same time just exposing the database directly over the wire would be just as easy and have the same issues. The flexibility is awesome but giving that much power to an app seems dangerous unless you're writing pure data services. I could see this route being more appropriate if you had a reporting DB though. I also see value add when you're putting a single API over separate services (such as MS Graph).



· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Thanks @cooldadtx

I am also not in favor of exposing IQueryable but considering any approach means OData or GraphQL, how to deal with large data in a table( 300K+).
I can write server side filtering and pagination using EF core but how can we achieve using either OData or GraphQL.
Using server side filtering and pagination leads in writing more code and number of controller methods with different parameters.
So now I am stuck here, how to do it in better way

0 Votes 0 ·

OData pretty much mandates using IQueryable. But you said from your repository. This always triggers the classic "repo is an anti-pattern" argument. Personally I think repos make sense but they are an abstraction (for testing). Your repo impl is going to have to expose IQueryable which is not really testable (correctly). So I would argue that there might be very little reason to use a repo for this. If you do then your repo should really only contain the mutator methods you need. Any queries will be done via IQueryable anyway. But exposing IQueryable means you have no control over the queries being run.

Honestly I like the OData ability to query and filter objects but I don't want it to give access to the entire structure. I'm personally looking at using MS's OData library's parser to allow me to write an API that supports OData filters (and possibly selection, expansion) without being tied to the DB. It is supported and there are examples online but it is complex. However this allows me to control what queries/filters can be run and doesn't require exposing IQueryable. I personally use CQS so filtering is just a LINQ expression that I have to project from the API model to my EF context by hand, in theory at least. Haven't gotten it working yet.

1 Vote 1 ·