2016-11-01 2 views
0

У меня есть 4-слойный архитектурный проект, то есть UserInterface, BusinessLogic, Service (WCF) и DataAccess (EF6). Я выставил методы моей службы, которые принимают выражение, которое я могу передать на мой уровень данных, который будет оцениваться с использованием EF. Однако это не работает, потому что выражение не сериализуемо.Как работать с Expression Деревья не работают с WCF, так как они не могут быть сериализованы?

На моем конце клиента я хочу иметь возможность создавать запросы для отправки на сервер и возвращать правильную проекцию.

стороне сервера:

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

Клиент сторона:

public IEnumberable<PersonDto> GetFromService(Expression<Func<PersonDto, bool>> expression) 
     { 
      using (MyService client = new MyService()) 
      { 
       return client.Get(expression); 
      } 
     } 

Есть ли альтернатива, как я делаю это? И есть ли причина, почему выражения и функции не могут быть сериализованы?

+1

Вы можете попробовать использовать эту библиотеку: https://github.com/esskar/Serialize.Linq – Evk

+1

Alreay ответил здесь: https://stackoverflow.com/questions/567316/can-you-pass-funct-bool-through-a-wcf-service –

+0

Есть ли причина для сериализации дерева выражений по строковым критериям? то есть передать строковые критерии серверу, который затем создает дерево выражений. Сериализация деревьев выражений добавляет сложность/накладные расходы, что затрудняет отладку/устранение проблем. –

ответ

3

Для этого можно использовать Remote.Linq. Проект в настоящее время размещен на GitHub, но, похоже, нет документации. Но вы можете использовать old one от CodePlex.

Самый простой способ добиться этого (код, скопированный из старой документации)

// 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>(); 
3

Для вашего конкретного сценария, было бы проще (и, вероятно, более безопасно), чтобы просто передать WHERE условие в виде строки и используйте динамический linq на сервере.

using System.Linq.Dynamic; 

public virtual IEnumerable<Person> Get(string condition) 
    { 
     using (var ctx = MyContext()) 
     { 
      return = ctx.DbContext.People.Where(condition).ToList(); 
     } 
    } 

Больше информации здесь: Using the LINQ Dynamic Query Library

Смежные вопросы