вложенный Any in не работает в динамическом linq

Мы предлагаем нашим пользователям возможность создавать собственные запросы к данным. Для выполнения этой работы мы используем библиотеку 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; }
}

}


person k.c.    schedule 15.06.2015    source источник
comment
Просто чтобы быть уверенным, какую динамическую библиотеку Linq вы используете?   -  person Stefan    schedule 15.06.2015
comment
И можете ли вы показать нам динамический оператор linq до его выполнения, и если вы выполняете его для базы данных, также SQL?   -  person Stefan    schedule 15.06.2015
comment
@stefan Я использую System.Linq.Dynamic 1.0.4 версии kahanu   -  person k.c.    schedule 15.06.2015
comment
@Stefan: SQL не выполняется. Он взрывается System.Linq.Dynamic.ParesException. У меня есть трассировка стека длиннее моей ноги, если вам интересно?   -  person k.c.    schedule 15.06.2015
comment
Да, это полезно. И, если хотите, еще немного о том, как вы строите запрос.   -  person Stefan    schedule 15.06.2015
comment
Ваши круглые скобки не закрыты должным образом ни в одном из примеров (5 открытых, 4 закрытых).   -  person Radu Balaban    schedule 15.06.2015
comment
@RaduB извините за это, исправил это в тексте вопроса. В коде присутствовали все скобки.   -  person k.c.    schedule 16.06.2015
comment
@Stefan: я добавил трассировку стека к вопросу   -  person k.c.    schedule 16.06.2015
comment
Хм, трассировка стека не проливает на это много света. Можете ли вы опубликовать полную строку примера? И как построена строка? Возможно, есть возможность как-то изменить порядок.   -  person Stefan    schedule 16.06.2015
comment
@Stefan: Это часть проблемы. Пользователи могут создать любое количество предикатов с помощью нашего построителя запросов и связать их вместе, используя И и ИЛИ по своему усмотрению. Теперь я делаю комбинации как конкатенацию строковых элементов в одну огромную динамическую строку linq. Если нет динамической библиотеки linq, которая правильно справляется с этим, мне придется прибегнуть к объединению отдельных предикатов с объединениями и пересечениями. Это потребует некоторых усилий, но даст возможность сбежать...   -  person k.c.    schedule 16.06.2015
comment
@Stefan: я добавил полный пример кода, который устраняет проблему до голых костей. но выдает ту же ошибку   -  person k.c.    schedule 17.06.2015
comment
Спасибо, я посмотрю на это.   -  person Stefan    schedule 17.06.2015
comment
Есть ли у вас какие-либо обновления? На самом деле я столкнулся с той же проблемой с вложенным .Any, использующим System.Linq.Dynamic 1.0.4 от kahanu.   -  person niklr    schedule 23.10.2015


Ответы (3)



Кажется, он работает с оригинальным исходным кодом, который можно скачать здесь: https://msdn.microsoft.com/en-US/vstudio/bb894665.aspx

Просто используйте класс CSharpSamples\LinqSamples\DynamicQuery\DynamicQuery\Dynamic.cs вместо пакета System.Linq.Dynamic NuGet.

person niklr    schedule 22.10.2015
comment
Спасибо, я тем временем перешел к другим вещам, так что пройдет некоторое время, прежде чем я смогу попробовать. - person k.c.; 23.10.2015

Уже отлично работает в моей ветке из этой библиотеки: System.Linq. Dynamic.Core

person Stef Heyenrath    schedule 02.02.2017