Reputation: 5283
I have a 4 layered architecture project, i.e. UserInterface, BusinessLogic, Service (WCF) and DataAccess (EF6) layers. I have exposed methods on my service that accept an expression which I can pass to my data access layer to be evaluated using EF. However, this does not work because the Expression<Func>
is not serializable.
On my client end I want to be able to build queryable expressions to send to the server side and return the correct projection.
Server Side:
public virtual IEnumerable<Person> Get(Expression<Func<Person, bool>> expression)
{
using (var ctx = MyContext())
{
IQueryable<PersonDto> col = ctx.DbContext.People.Where(expression);
//
return col.ToList();
}
}
Client side:
public IEnumerable<PersonDto> GetFromService(Expression<Func<PersonDto, bool>> expression)
{
using (MyService client = new MyService())
{
return client.Get(expression);
}
}
Is there an alternative to the way I'm doing this? And is there a reason why expressions and funcs are not serializable?
Upvotes: 1
Views: 463
Reputation: 180908
For your particular scenario, it would be simpler (and probably more secure) to just pass the WHERE condition as a string and use dynamic linq on the server.
using System.Linq.Dynamic;
public virtual IEnumerable<Person> Get(string condition)
{
using (var ctx = MyContext())
{
return = ctx.DbContext.People.Where(condition).ToList();
}
}
More info here: Using the LINQ Dynamic Query Library
Upvotes: 3
Reputation: 2581
You can use Remote.Linq for this. The Project is currently hosted on GitHub, but it seems that there is no documentation. But you can use the old one from CodePlex.
The easiest way to achieve this (Code copied from the old documentation)
// create linq expression
System.Linq.Expressions.Expression<Func<Order, bool>> linqExpression =
order => order.Items.Where(i => i.ProductId == prodId).Sum(i => i.Quantity) > 1;
// transform linq expression into serializable expression tree
Remote.Linq.Expressions.LambdaExpression serializableExpression =
linqExpression.ToRemoteLinqExpression();
// transform serializable expression tree back into linq expression
System.Linq.Expressions.Expression<Func<Order, bool>> recreatedLinqExpression =
serializableExpression.ToLinqExpression<Order, bool>();
Upvotes: 4