Comments (9)
Actually we use ODataQueryOptions.Apply()
to apply to an IQueryable<T>
returned by IEnumerable<T>.AsQueryable()
in case of §apply and aggregate cases.
The OData-Query-Options do not translate to SQL because the produced LINQ-Query does not work with EF Core (Were able to build those LINQ-Queries manually and run successfully but with OData did not work).
So as a workaround we call ToArray()
to materialize the data and on the returning array we call AsQueryable()
to apply the OData-Query-Options on the resulting IQueryable<T>
.
That means you got to load the whole dataset into memory before applying the query.
But you can return a filtered dataset to the client.
Thats not perfect but at least you do not have to return the whole dataset.
Because you can apply to IQueryable<T>
returned from IEnumerable<T>.AsQueryable()
you can also apply to any Array/List nevermind where you pulled the data from.
The following Example shows a very specific case of ours, of course you could have loaded your array from anywhere else and using an ODataController instead of an generic ApiController.
Example:
[ApiController]
public class AggregateController<TEntity> : ControllerBase
{
private readonly MyContext _myContext;
public AggregateController(MyContext myContext)
{
_myContext = myContext;
}
[HttpGet("")]
public async Task<IActionResult> Aggregate(ODataQueryOptions<TEntity> queryOptions)
{
var dbSet = _myContext.Set<TEntity>();
var dataArray = dbSet.ToArray();
IQueryable query = queryOptions.ApplyTo(dataArray().AsQueryable());
return Ok(query);
}
}
from aspnetcoreodata.
Hi @jan-johansson-mr, to start the discussion, this is probably a question regarding to your data provider. Does it support the same IQueryable extension methods as for example Sql server providers does? If yes, than you are ready to go.
IMO OData.Net is data store agnostic.
from aspnetcoreodata.
Regarding to the sample, here I tried to approach a nosql MongoDb OData: https://github.com/tomasfabian/Joker/tree/master/Samples/MongoDb
I believe that in the result you have to accomplish the same CRUD operations.
from aspnetcoreodata.
Hi @tomasfabian,
Thanks for your provided sample.
My thoughts on OData is if we are able to use it, without being hard coupled to some DB provider. In essence, how do we, as developers, write an adapter that OData needs to access the data pool? If we can do that, then we can plug in any type of store for OData. E.g. in-memory store, or whatever we have in mind. I'm sure it is possible. The question is how we do it, and how much work is it to do?
And of course, is there a sample of some in-memory adapter (provider) for OData available?
from aspnetcoreodata.
@jan-johansson-mr I think the comments from @tomasfabian is correct. OData doesn't care about the Data source or data provider.
Your question " If we can do that, then we can plug in any type of store for OData. E.g. in-memory store", Can you share more detail about your thoughts?
from aspnetcoreodata.
Hi, Thanks for your reply. @tomasfabian is correct, however, my concern is not so much about plugging in one provider or another, my concern is if it is possible to plugin a provider that is not tied to some database, e.g. an in-memory store. My thoughts are that I want to resolve data through other means than query a database, e.g. memory or via some service. But also, in more advanced scenarios that some data may be pulled from services while others from memory. Or if I have a repository pattern on-top of some store, so I want OData to use my repository rather than direct store access. Is this possible?
Thanks
from aspnetcoreodata.
Hi @jan-johansson-mr,
I think that my answer still applies. OData does not care about the data source. You can inject your IRepository into your ODataController or into another service.
This example is for WebApi, but you can achieve the same with AspNetCore.OData.
For retrieving data you should return IQueryable<TEntity>
from your repository in order to be able to use filtering etc., but this depends on your data provider. It is up to you whether you able or would like to support operators like Expand, Top etc. They can be disabled if you can't support these operators. But in these cases you should probably switch to AspNetCore WebApi. It also supports IAsyncEnumerable<T>
. AFAIK OData does not support it.
Create, update and delete operations should be straightforward to implement even for in memory stores or you could redirect it to another web service.
So at the end you should be able to mix different data sources and they do not have to be some kind of database IMO.
@xuzhg let us know in case I'm not correct for some reasons. Thx
from aspnetcoreodata.
Thanks @JanKotschenreuther, it's a nice trick, and I do share your reflections on up and downsides to the trick. My concern with OData is that it is a kind of black box "SQL" on HTTP. OData does not delegate how to resolve data (GraphQL does) but "owns" the data to filter and aggregate. Therefore OData needs all access to all data to do the work (with some provider as EF, or as in your case a neat trick with some ups and downs). And to implement a provider as EF takes years. As I recall reading that such a provider basically dwarf almost any application by leaps and bounds in complexity. My original question was that if OData was able to delegate how to resolve data and if so how that was done and if there were some examples of that.
from aspnetcoreodata.
Hi @jan-johansson-mr,
OData basically translates HTTP requests to an AST and then to SQL or MQL for unstructured data, etc., with some kind of provider as you've already mentioned. These providers are using the aforementioned IQueryable<T>
interface. This interface has a lot of extension methods and an expression visitor is used to generate a string (URL. SQL) query from them. The same magic is used on the client side if you are using OData client (DataServiceContext). So my point is that there is only one http request or one provider (EF core) query at the end (of course can depend on the internal implementation).
If I understand you correctly you would like to combine the end result of an OData query from different data sources. OData AFAIK doesn't have a similar concept to GraphQL's resolvers.
On the other hand I think that with OData you probably don't have to solve the n+1 problem, because it will generate a JOIN clause from $Expands, etc. In GraphQL you have to implement some kind of batch Data Loader in order to achieve this. In most cases a Data loader only moves this issue from clients to the server (it depends on the implementation).
So I don't think that it is possible to easily (out of the box) combine a result from e.g. MongoDb, Redis, REST API or SQL server, etc. with ONE OData query.
Do you agree @xuzhg?
from aspnetcoreodata.
Related Issues (20)
- $filter function does not work correctly with DateTime fields HOT 1
- Instance Annotations for properties with $select query option HOT 1
- Custom FilterBinder doesn't work on actions with querying via ODataQueryOptionParser HOT 7
- It's still not clear how to filter by enum property HOT 7
- How to define `EDM model` that add subquery on control to `OData Endpoint Mapping`? HOT 3
- How do I use the month function of date type in a group query
- WebApiAssembliesResolver class missing causing slow model build HOT 2
- Allow casting Edm.Untyped to a primitive type for `$filter`ing when the other operand is also a primitive HOT 4
- There seems to be an issue with case conversion when using Newtonsoft, I don't know yet if it's just case HOT 5
- Passing a Complex object in the ODATA function HOT 5
- Faulty link generation when creating entities with string key and slashes HOT 1
- NullReference exception generated when using FilterClause.ApplyTo method with open properties in the filter query HOT 2
- Case sensitive issue on ODatadynamic Model HOT 2
- Conflicting routes when using NSwag and OData HOT 6
- Data not loaded correctly in Excel and Power BI Desktop with the use of $expand in OData feed HOT 10
- OData DeepInsert not binding correctly HOT 3
- Strange time zone propagation in the filter HOT 2
- Select query throw an error on a dynamic property dictionary HOT 7
- OData + EfCore Filter dynamic properties HOT 2
- FEATURE REQUEST: be able to conditionally omit properties from response payloads HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from aspnetcoreodata.