oronsultan Ответов: 1

Как использовать system. linq. dynamic для построения динамического предложения where


Эй, ребята, что случилось?

Сейчас мы работаем над проектом в моей компании (C # & ASP.Net) и на одной из страниц есть механизм, который извлекает некоторые данные из таблицы с помощью WCF.

Пока все так хорошо!

эти данные хранятся внутри класса DTO (назовем его Tikun94ActualPerformanceSummaryDto), и в конечном итоге я преобразую их в такой объект IEnumerable:
IEnumerable<Tikun94ActualPerformanceSummaryDTO> filtered = this.Tikun94Summaries as IEnumerable<Tikun94ActualPerformanceSummaryDTO>;

(Tikun94Summaries - это объект типа Tikun94ActualPerformanceSummaryDto).

Теперь эти данные просматриваются через таблицу на странице, и пользователь может отфильтровать таблицу, используя несколько вариантов, которые я ему даю.
Нажимая кнопку "Отправить", я хочу перебрать существующий "фильтр" (типа IEnumerable, который я создал ранее) и отфильтровать его по значениям, данным мне пользователем.

Для каждого значения, заданного пользователем, мне нужно установить предложение Where, которое фильтр "фильтрует" снова и снова. Теперь, поскольку я не хочу снова и снова запрашивать один и тот же IEnumerable "filtered" , я хочу построить Where динамически
и чем запустить его только один раз.

Давайте посмотрим немного кода:
IEnumerable<Tikun94ActualPerformanceSummaryDTO> filtered = this.Tikun94Summaries as IEnumerable<Tikun94ActualPerformanceSummaryDTO>;
            IQueryable<Tikun94ActualPerformanceSummaryDTO> queryableData = filtered.AsQueryable();

Здесь (выше), как вы можете видеть, я начинаю с преобразования объекта IEnumerable в объект IQueryable, чтобы сделать следующее:

string query = "filtered.Where(";

Теперь я начинаю проверять значения, заданные пользователем, и устанавливаю Where в соответствии с ними, используя switch Case (возьмем в качестве примера 2 случая):
#region OperatorLineId

switch (cmbLine.SelectedValue)
            {
                case "0":
                    query += += "u => u.OperatorLineId == u.OperatorLineId  ";
                    break;
                default:
                    query += "u => u.OperatorLineId == Convert.ToInt32(cmbLine.SelectedValue) ";
                    break;
            }
#endregion

#region ExclusivityLine 
switch (ddlExclusivityLine.SelectedValue)
            {
                case "0":
                    query += "AND u => u.ExclusivityLine == u.ExclusivityLine ";
                    break;
                default:
                    query += "AND u => u.ExclusivityLine == ddlExclusivityLine.SelectedValue )";
                    break;
            }
            #endregion

var externals = new Dictionary<string, object>();
            externals.Add("filtered", queryableData);

И вот тут я получаю экзекуцию :-( :
var expression = System.Linq.Dynamic.DynamicExpression.Parse(typeof(IQueryable<Tikun94ActualPerformanceSummaryDTO>), query, new[] {externals});

Сообщение об исключении:
"Никакое свойство или поле" у " существует в тип 'Tikun94ActualPerformanceSummaryDto'"

У меня есть несколько догадок о том, что я делал неправильно. Может быть, я пытаюсь использовать лямбда-выражение там, где мне это не положено, и, возможно, я не получаю прямого доступа к элементам внутри DTO cuu. Мотыга могу ли я получить доступ к значениям внутри DTO? может быть, я не должен?

В конце концов, я хочу построить это предложение Where динамически (в некоторых случаях переключения я должен использовать оператор '>' или '<').

Я предполагаю, что у меня есть более чем одна ошибка при написании этого алгоритма, и я хотел бы знать, каков правильный синтаксис для написания этой операции.

Это класс Tikun94ActualPerformanceSummaryDto (там, конечно, есть еще много параметров, но здесь это просто пример):
using System;
using WcfSerialization = global::System.Runtime.Serialization;

namespace OpsReporting.DataContracts
{
    [WcfSerialization::DataContract(Namespace = "urn:OperatorsReporting.ServiceContracts", Name = "Tikun94ActualPerformanceParamDTO")]
	public partial class Tikun94ActualPerformanceSummaryDTO
    {
        public int operatorLineId;
        public string exclusivityLine;
        
        [WcfSerialization::DataMember(Name = "OperatorLineId", IsRequired = true, Order = 6)]
        public int OperatorLineId
        {
            get { return operatorLineId; }
            set { operatorLineId = value; }
        }

        [WcfSerialization::DataMember(Name = "ExclusivityLine", IsRequired = true, Order = 8)]
        public string ExclusivityLine
        {
            get { return exclusivityLine; }
            set { exclusivityLine = value; }
        }    
}



Большое спасибо!

Что я уже пробовал:

Лоты: см. выше

1 Ответов

Рейтинг:
12

Ehsan Sajjad

В динамическом linq строковый параметр передается просто обычным sql, а не какими-либо лямбда-выражениями, поэтому ваше условие должно быть таким:

 case "0":
       query += "OperatorLineId = OperatorLineId  ";
       break;
default:
      query += string.Format("OperatorLineId = {0}",Convert.ToInt32(cmbLine.SelectedValue));

var result = filtered.Where(query);


возможно, вы захотите Подробнее читайте в этой статье. или подумайте о том, чтобы проверить эту статью о динамические запросы Linq to Entities с использованием WCF


oronsultan

Уважаемый Эхсана,
спасибо за быстрый ответ.
Я пытался сделать это раньше (и попробовал сделать это позже после вашего ответа), но все, что я получаю, - это это исключение:
"Выражение типа' IQueryable ' 1 'expected".
Я погуглил его и ничего не нашел.
Кстати, это происходит в той же кодовой строке, что и befor. Есть идеи?

Ehsan Sajjad

ваш запрос, где часть предложения не должна быть строковым литералом, должен быть таким : `var result = filtered.Где (запрос);`

oronsultan

это невозможно написать ' var result = filtered.Where (query);', 'where' не принимает строку. не могли бы вы помочь мне, пожалуйста, с синтаксисом?

oronsultan

это невозможно написать ' var result = filtered.Where (query);', 'where' не принимает строку. не могли бы вы помочь мне, пожалуйста, с синтаксисом?

Ehsan Sajjad

если вы добавили ссылку на DynamicLinq, а затем добавили using поверх класса, вы должны иметь возможность использовать метод Where, который принимает строку в качестве входных данных