Мы предлагаем нашим пользователям возможность создавать собственные запросы к данным. Для выполнения этой работы мы используем библиотеку Dynamic LINQ. Эта конструкция вызывает у нас проблемы: у нас есть набор лиц, которые мы запрашиваем следующим образом:
( DossierItems.Any( DossierFiles.Any())) && ( FirstName.Contains( \"h\" ) )
Это приводит к ошибке, указывающей, что:
В типе «DossierItem» нет свойства или поля «Имя».
Что совершенно правильно: Имя — это свойство человека. Закрывающая скобка после второго «любого» почему-то пропущена.
( FirstName.Contains( \"h\" ) ) && ( DossierItems.Any( DossierFiles.Any() ) )
Приведенный выше оператор прекрасно работает, но мы не можем контролировать порядок, в котором вводятся предикаты.
Есть ли способ изменить вложенные части Any, чтобы игра была приятной с любыми следующими предикатами?
Это трассировка стека, созданная Dynamic Linq при анализе строки динамического linq:
at System.Linq.Dynamic.ExpressionParser.ParseMemberAccess(Type type, Expression instance)
at System.Linq.Dynamic.ExpressionParser.ParseIdentifier()
at System.Linq.Dynamic.ExpressionParser.ParsePrimaryStart()
at System.Linq.Dynamic.ExpressionParser.ParsePrimary()
at System.Linq.Dynamic.ExpressionParser.ParseUnary()
at System.Linq.Dynamic.ExpressionParser.ParseMultiplicative()
at System.Linq.Dynamic.ExpressionParser.ParseAdditive()
at System.Linq.Dynamic.ExpressionParser.ParseComparison()
at System.Linq.Dynamic.ExpressionParser.ParseLogicalAnd()
at System.Linq.Dynamic.ExpressionParser.ParseLogicalOr()
at System.Linq.Dynamic.ExpressionParser.ParseExpression()
at System.Linq.Dynamic.ExpressionParser.ParseParenExpression()
at System.Linq.Dynamic.ExpressionParser.ParsePrimaryStart()
at System.Linq.Dynamic.ExpressionParser.ParsePrimary()
at System.Linq.Dynamic.ExpressionParser.ParseUnary()
at System.Linq.Dynamic.ExpressionParser.ParseMultiplicative()
at System.Linq.Dynamic.ExpressionParser.ParseAdditive()
at System.Linq.Dynamic.ExpressionParser.ParseComparison()
at System.Linq.Dynamic.ExpressionParser.ParseLogicalAnd()
at System.Linq.Dynamic.ExpressionParser.ParseLogicalOr()
at System.Linq.Dynamic.ExpressionParser.ParseExpression()
at System.Linq.Dynamic.ExpressionParser.Parse(Type resultType)
at System.Linq.Dynamic.DynamicExpression.ParseLambda(ParameterExpression[] parameters, Type resultType, String expression, Object[] values)
at System.Linq.Dynamic.DynamicExpression.ParseLambda(Type itType, Type resultType, String expression, Object[] values)
at System.Linq.Dynamic.DynamicQueryable.Where(IQueryable source, String predicate, Object[] values)
at Repositories.Base.Repository`1.ApplyQuery(IQueryable`1 entities, Guid queryId)
at Search.SearchQueryResult.RunQuery[T](IQueryable`1 entities, IRepository`1 repository)
Пример кода для воспроизведения
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using System.Linq.Dynamic;
пространство имен ClassLibrary1 {
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
// arrange
var allAs = new List<A>();
// act
// pass
var actual = allAs.Where("(Name = \"\")&&(Bs.Any(Cs.Any()))");
// fail
var actual = allAs.Where("(Bs.Any(Cs.Any()))&&(Name = \"\")");
}
}
public class A
{
public string Name { get; set; }
public IList<B> Bs
{
get { return bs; }
set { bs = value; }
}
private IList<B> bs = new List<B>(0);
}
public class B
{
public A A { get; set; }
public IList<C> Cs
{
get { return cs; }
set { cs = value; }
}
private IList<C> cs = new List<C>(0);
}
public class C
{
public B B { get; set; }
}
}