I've been learning about IQueryable and lazy loading/deferred execution of queries.
Is it possible to expose this functionality over WCF? I'd like to expose a LINQ-to-SQL service that returns an IQueryable which I can then perform additional queries on at the client, and finally execute using a .ToList(). Is OData format applicable at all in this context?
If possible, what is the term for this technique and what are some good tutorials I can follow? Thank you.
You should check WCF Data Services which will allow you to define Linq query on the client. WCF Data Services are probably the only solution for your requirement.
IQueryable is still only interface and the functionality depends on the type implementing the interface. You can't directly expose Linq-To-Sql or Linq-To-Entities queries. There are multiple reasons like short living contexts or serialization which will execute the query so the client will get list of all objects instead of the query.
as far as i know, the datacontext is not serializable meaning that you cannot pass it around with WCF
You can use http://interlinq.codeplex.com/ which allows you to send Linq query over WCF.
WCF Data Services only can be using with webHttpBinding and not all Linq queries can be expressed. Writing queries when WCF Data Service is used is not so attractive - requires string expressions such as:
.AddQueryOption("$filter", "Id eq 100");
https://remotelinq.codeplex.com/ is another choice. But it works in AppDomain to scan the Current Assemblies and serialize them. This tech is not suitable to WinRT as no Domains for WinRT App
I've been struggling with the same question, and realized that a well formed question is a problem solved.
IQueryable basically serves to filter the query before sending it to your DB call so instead of getting 1000 records and filter only 10, you get those 10 to begin with. That filtering belongs to your Service Layer, but if you are building an API I would assume you would map it with AND/OR parameters in your URL.
http://{host}/{entity}/q?name=john&age=21.
So you end up with something like this:
Filter:Column1=Value1 > http://{host}/{entity}q?column1=value1 > SELECT *
FROM Entity
WHERE Column1=Value1
MVC > WCF > DB
You can find a very good sample [here]
Lastly, since your payload from the WCF will be most likely a JSON, you can (and should) then deserialize them in your Domain Models inside a collection. It is until this point where the paging should occur, so I would recommend some WCF caching (and since its HTTP, it's really simple). You still will be using LINQ on the WebApp side, just w/o "WHERE" LINQ clause (unless you want to dynamically create the URL expressed above?)
For a complex OR query, you mind end up with multiple WCF queries (1 per "AND") and then concatenate them all together
If it's possible to send IQuerable<> over WCF it's not a good thing security wise, since IQuerable<> could expose stuff like the connection string to the database.
Some of the previous comments seem promising though.
Related
I have start working on project using SPARQL and springboot. How to managing very large SPARSQL queries? What is the right place to implement them in project? Currently I am just using methods with Springbuilder and returned a query as a String.
Constructing your queries as a String is fine, as long as you are very careful when injecting any user-provided input into your query.
A safer approach is to use a query builder, such as the RDF4J SparqlBuilder, so you can construct your queries in a fluent API, e.g. like this:
// SELECT ?product where { ?product a ex:book }
selectQuery.prefix(ex).select(product).where(product.isA(ex.iri("book"));
As for where to manage this stuff in your project, it depends a bit of the APIs you're using, but assuming you're using RDF4J, for example, I would typically recommend some variation of a DAO pattern, and creating your DAO class by means of a repository (connection) wrapper object.
I'm building a Graphene-Django based GraphQL API. One of my colleagues, who is building an Angular client that will use the API, has asked if there's a way to store frequently used queries somehow on the server-side so that he can just call them by name?
I have not yet encountered such functionality so am not sure if it's even possible.
FYI he is using the Apollo Client so maybe such "named" queries is strictly client-side? Here's a page he referred me to: http://dev.apollodata.com/angular2/cache-updates.html
Robert
Excellent question! I think the thing you are looking for is called "persisted queries." The GraphQL spec only outlines
A Type System for a schema
A formal language for queries
How to validate/execute a query against a schema
Beyond that, it is up to the implementation to make specific optimizations. There are a few ways to do persisted queries, and different ones may be more or less helpful for your project.
Storing Queries as a String
Queries can easily be stored as Strings, and the convention is to use *.gql files to do that. Many editors/IDEs will even have syntax highlighting for this. To consume them later, just URL Encode them, and you're all set! Since these strings are "known" you can whitelist the requests on the server if you choose.
const myQuery = `
{
user {
firstName
lastName
}
}
`
const query = `www.myserver.com/query=${urlEncode(myQuery)}`
Persisted Queries
For a more sophisticated approach, you can take queries that are extracted from your project (either from strings or using a build tool), pre-run them and put the result in a DB. This is what Facebook does. There are plenty of tools out there to help you with this, and the Awesome-GraphQL repo is a good place to start looking.
Resources
Check out this blog for more info on Persisted Queries
Within the context of C# on .Net 4.0, are there any built-in objects that implement IQueryable<T>?
IQueryable objects are produced by Queryable Providers (ex. LINQ to SQL, LINQ to Entities/Entity Framework, etc). Virtually nothing you can instantiate with new in the basic .NET Framework implements IQueryable.
IQueryable is an interface designed to be used to create Queryable providers, which allow the LINQ library to be leveraged against an external data store by building a parse-able expression tree. By nature, Queryables require a context - information regarding what exactly you're querying. Using new to create any IQueryable type, regardless of whether it's possible, doesn't get you very far.
That being said, any IEnumerable can be converted into an IQueryable by using the AsQueryable() extension method. This creates a superficially-similar, but functionally very different construct behind the scenes as when using LINQ methods against a plain IEnumerable object. This is probably the most plentiful source of queryables you have access to without setting up an actual IQueryable provider. This changeover is very useful for unit-testing LINQ-based algorithms as you don't need the actual data store, just a list of in-memory data that can imitate it.
Well, your question is kinda weird... but I believe that if you look at an interface in Reflector, it will give you a list of implementers in the loaded assemblies.
As a disclaimer I have not used Reflector since it went pay-for-play so I might be wrong.
EntityCollection does, as does EnumerableQuery.
Not that I think either of these is going to get you anywhere. To help, we need to know what you are really trying to solve. If you are writing a LINQ provider, you should read this: http://msdn.microsoft.com/en-us/library/bb546158.aspx.
They recommend writing your own implementation.
If you are looking for a way to instantiate an empty list of IQueryable, then you can use this:
IQueryable<MyEntity> = Enumerable.Empty<MyEntity>().AsQueryable()
I've got a REST web service that uses LinqtoNh to query entities and return them as DTO, plain classical stuff. I want the service to apply some filter/order clause on the returned entities, and I'm asking if there is some way of serialize the linqtonh expression in order to send it an the wire without creating some custom strategy. A plus would be not having a NH reference on the client.
Any suggestion?
Take a look at WCF Ria Services: It expose a WCF Rest service that supports the LINQ filtering, sorting, paging e grouping.
Server side the DomainService will create a LINQ query with "Where", "Order*", "Take", "Skip"...
Avoiding the NH reference it's a great idea, implement your own IQueryable, link it to NHibernate (maybe you want to use an IoC engine to do so) and return it in the exposed queries! You're almost done, most of the LINQ2NH call are standard LINQ extensions method, you would have to write somethign else if you need to use the eager fetching extension method (Fetch*) or other pretty NHibernate-stuff.
As far the client, WCF Ria is initially designed for SL but supports everything, they have even JS client called RIA/JS
I understand that a IQueryable cannot be serialized. That means that queries can not be serialized, sent to a webservice, deserialized, queried and then sent back.
I was wondering if it is possible to convert a hibernate linq query to hql to be sent over the wire.
Is there another route I am missing?
I think I've seen ADO.NET Data Services as advertised to work with NHibernate:
http://wildermuth.com/2008/07/20/Silverlight_2_NHibernate_LINQ_==_Sweet
http://ayende.com/Blog/archive/2008/07/21/ADO.Net-Data-Services-with-NHibernate.aspx
This is an old post, and not sure how maintained this feature is, but its worth a shot.
I have a suggestion to you. Do not try to serialize query. Rather provide your user with an ability to compose arbitrary LINQ expression. Then send the expression over the wire (there is a gotcha here, since expressions are not serializable) to your server.
I have recently submitted to NHibernate.Linq project a change to their NHibernateExtensions class - a new ISession extension method List, which accepts an expression and fills the given list with the respective data, much like ICriteria.List method. The change was accepted (see here) so downloading the recent version of NHibernate.Linq should contain this method.
Anyway, you can find the details of this approach here.