How to work with Expression Trees not working using WCF since they are not serializable?

末鹿安然 提交于 2019-12-11 04:21:59

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!