Serializing a LinqtoNh filter/order clause - linq

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

Related

OData accent-insensitive filter

How can I apply a filter accent-insensitive? In OData the "eq" operator is case and accent sensitive. The case is easy to fix, because the "tolower" but relative to the accent I'm not getting a simple solution. I know contains is supposed to be accent-insensitive but if I use contains filtering by "São José" I am only getting these responses "São José" and "São José dos Campos", it is missing "Sao Jose".
The following example filtering by "Florianopolis" is expected to return "Florianópolis", but it does not:
url: api/cidades/get?$filter=contains(nome, 'Florianopolis')
[HttpGet]
[EnableQuery]
public ActionResult<IQueryable<CidadeDTO>> Get()
{
try
{
return Ok(_mapper.Map<IEnumerable<CidadeDTO>>(_db.Cidades));
}
catch (System.Exception e)
{
return BadRequest(e.GetBaseException().Message);
}
}
It should bring aswell, like entity framework.
If your OData model was mapped directly to EF models AND an IQueryable<T> expression was passed into OK() then the query is explicitly passed through to the database engine as SQL:
SELECT * FROM Cidades WHERE nome LIKE '%Florianopolis%'
When that occurs, the Collation settings in the database connection will determine the comparison matching logic.
When your database collation is case and accent insensitive, but your data is still filtered as if it was not, then this is an indication that an IEnumerable<T> has been passed into OK() and the comparison logic is being evaluated in C# which by default in insensitive to both case and accent. Unfortunately this means that it is very likely that the entire data table has been loaded into memory first so that the filter can be applied.
In your case the OData model is mapped to DTO expressions that are mapped to the EF models via AutoMapper and that is where the generated query can break down. By calling Map() you are loading ALL records from the EF table and leaving the $filter criteria to be applied by the EnableQueryAttribute
For OData query conventions to be applied automatically you must return an IQueryable<T> from your method, or atleast pass an IQueryable<T> into the OK() response handler. With AutoMapper, you can use the Queryable Extensions to satisfy the IQueryable<T> requirement:
Queryable Extensions
When using an ORM such as NHibernate or Entity Framework with AutoMapper’s standard mapper.Map functions, you may notice that the ORM will query all the fields of all the objects within a graph when AutoMapper is attempting to map the results to a destination type.
...
ProjectTo must be the last call in the chain. ORMs work with entities, not DTOs. So apply any filtering and sorting on entities and, as the last step, project to DTOs.
In OData the last requirement (about ProjectTo) is still problematic because the EnableQueryAttribute will append the query options to the IQueryable<T> response, which will still end up materializing the entire table into memory first (IEnumerable<T>) and then apply the filter, which is still incredibly inefficient. It is this behaviour that is generally observed when someone complains about poor performance from an OData implementation, it is not always AutoMapper, but usually the pattern that the data source is loaded into memory in its entirety and then filtered. Following the default guidance for AutoMapper will lead you in this direction.
Instead we need to use an additional package: AutoMapper.Extensions.ExpressionMapping that will give us access to the UseAsDataSource extension method.
UseAsDataSource
Mapping expressions to one another is a tedious and produces long ugly code.
UseAsDataSource().For<DTO>() makes this translation clean by not having to explicitly map expressions. It also calls ProjectTo<TDO>() for you as well, where applicable.
This changes your implementation to the following:
[HttpGet]
[EnableQuery]
public ActionResult<IQueryable<CidadeDTO>> Get()
{
return Ok(_db.Cidades.UseAsDataSource().For<CidadeDTO>());
}
Don't fall into the trap of assuming that AutoMapper is necessary or best practice for an OData API implementation. If you are not using the unique features that AutoMapper provides then adding an additional abstraction layer can end up over-complicating your solution.
I'm not against AutoMapper, I use it a lot for Integrations, ETL, GraphQL and non-DDD style data schemas where the DTO models are significantly different to the underlying EF/data storage models. But it is a maintenance and performance overhead that a simple DDD data model and OData API based solution can easily do without.
Don't hire an excavator when a simple shovel will do the job.
AutoMapper is a convention based ORM that can be useful when you want to change the structure between implementation layers in your code, traditionally you might map Business Domain models that may represent aggregates or have flattened structures to highly normalised Database models.
OData is also a convention based ORM. It was designed to facilitate many of the same operations that AutoAmpper provides with the exception of Flattening and Unflattening models. These operations are deferred to the EF engine. The types exposed via OData mapping are DTOs
If your DTO models are the same relational structure as your EF models, then you would generally not use AutoMapper at all, the OData Edm mapping is optimised specifically to manage this type of workload and is designed to be and has been integrated directly into the serialization layer, making the Edm truely Data Transfer Objects that only exist over the wire and in the client.
This did the job
[HttpGet]
public ActionResult<IQueryable<PessoaDTO>> Get(ODataQueryOptions<Pessoa> options)
{
try
{
var queryResult = options.ApplyTo(_db.Pessoas);
return Ok(queryResult);
}
catch (System.Exception e)
{
return BadRequest(e.GetBaseException().Message);
}
}

Parsing the result-set in DAO vs Service layer

Let's consider a use-case of loading a map with from the db.
Even though I use Hibernate, my use-case doesn't require the whole student entity, which is huge, to be loaded. I just need the above pair of values.
When I execute plain sql query using the Hibernate, the response is in the format of List .
Here's my questions.
Q) Should the parsing of that raw result-set take place in DAO layer or Service layer?
My opinion is that as I'm not executing any business logic (like filtering one of those students), the method in the DAO layer itself should parse those results, construct the map, and return that pairs.
Any other insights or fundamentals reg DAO vs Service layer would be highly appreciated.
The rule of thumb I use is:
Only return from your data layer exactly what your service layer is going to use. So in this case, I would parse the list and build your map before returning. All your service layer is interested in is the map so why bother with the rest?

use safe cast (as) with mongoDb C# driver and linq

I'm attempting to use Odata and web-api with mongoDb. The web-api library applies linq queries across an IQueryable in order to query it. One of the queries I'm required to support involves a cast. web-api returns an IQueryable with the expression
value.where(it => ((it.property as Child).Value == "example"));
This results in
Unable to determine the serialization information for the expression:
<TypeAs>it.Property.Value
is there a way to modify the expression once I get the IQueryable so that it performs an
is check and then a cast, as this is supported by the C# driver. Alternatively is there a library which provides this support already?

What instantiate-able types implementing IQueryable<T> are available in .Net 4.0?

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()

Expose IQueryable Over WCF Service

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.

Resources