问题
I have a 4 layered architectured 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 dataaccess layer to be evaluated using EF. However, this does not work because the Expression 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 IEnumberable<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?
回答1:
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>();
回答2:
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
来源:https://stackoverflow.com/questions/40361088/how-to-work-with-expression-trees-not-working-using-wcf-since-they-are-not-seria