Невозможно получить более одного результата при использовании System.Linq.Dynamic.Core для запроса списка объектов, имеющих словарь-член - PullRequest
0 голосов
/ 02 октября 2018

Я использую System.Linq.Dynamic.Core v1.0.8.18

Я сокращаю объект, который у меня есть - я удалил теги JSON для сериализации / десериализации, а такжеКонструктор. Ниже приведен сокращенный класс для позиции в заказе.Обратите внимание, что этот объект десериализован из JSON, и цель «другого» словаря состоит в том, чтобы захватить любую пару имя / значение, которая явно не определена в объекте (которая работает точно так же, как и при тестировании и производстве):

public partial class OrderRequestItem
{

    public string line_number { get; set; }
    public decimal quantity { get; set; }
    public string supplier_id { get; set; }
    public string supplier_aux_id { get; set; }
    public decimal unitprice { get; set; }
    public string description { get; set; }
    public string uom { get; set; }
    public IDictionary<string, object> other;

    public decimal extension
    {
        get
        {
            return unitprice * quantity;
        }
    }

    public bool validated { get; set; }
    public bool rejected { get; set; }
}

Я пытаюсь «разделить» заказ, используя следующий код на основе записи файла конфигурации JSON, в которой указываются поля, на которые следует разделить заказ (параметр 2):

   private List<OrderRequest> SplitOrder(OrderRequest originalOrder, string[] orderSplitLineItemFields = null)
    {
        var retval = new List<OrderRequest>();
        if (null == orderSplitLineItemFields || originalOrder.items.Count < 2) //Can't return more than one order if we don't have fields to split by, and we don't have at least 2 line items.
        {
            retval.Add(originalOrder);
        }
        else
        {
            var bareOrderHeader = (OrderRequest)originalOrder.DeepClone();
            bareOrderHeader.items.Clear();
            var firstLineItem = originalOrder.items[0];
            var validOrderSplitLineItemFields = new List<string>();
            var dynamicQueryBase =  new List<string>();
            int validFieldCount = 0;
            foreach (var field in orderSplitLineItemFields)
            {
                if (firstLineItem.HasProperty(field))
                {
                    validOrderSplitLineItemFields.Add(field);
                    dynamicQueryBase.Add(field + " = @" + validFieldCount++);
                }
                else if (null != firstLineItem.other[field])
                {
                    validOrderSplitLineItemFields.Add("other[\"" + field + "\"]");
                    dynamicQueryBase.Add("other[\"" + field + "\"]" + " = @" + validFieldCount++);
                }
            }
            if(validOrderSplitLineItemFields.Count<1) //Can't return more than one order if we don't have valid fields to split by.
            {
                retval.Add(originalOrder);
            }
            else //We have valid fields to split the order, so we might be able to return more than one order.
            {

                string distinctFields = String.Join(",", validOrderSplitLineItemFields);
                var distinctFieldValues = originalOrder.items.AsQueryable().Select(distinctFields).Distinct();
                var dynamicWhere = string.Join(" and ", dynamicQueryBase);
                var originalLineItems = originalOrder.items.AsQueryable();
                foreach (var distinctResult in distinctFieldValues)
                {
                    var newOrderSplit = (OrderRequest)bareOrderHeader.DeepClone();

                    var results = originalLineItems.Where(dynamicWhere, distinctResult);
                    foreach (var lineitem in results)
                    {
                        newOrderSplit.items.Add(lineitem);
                    }

                    retval.Add(newOrderSplit);
                }
            }
        }
        return retval;
    }

Поле, на которое я пытаюсь разделить, называется «required_delivery_date», которое правильно передается в функцию SplitOrder.Поскольку это не фактическое свойство OrderRequestItem, разделенный код проверяет (и фактически успешно) просматривает / находит словарную запись в свойстве «other» и соответственно добавляет поле в список динамических полей, по которым запрашивается- (Я делаю это так, потому что определенные свойства являются «обязательными», и я не смогу предсказать, какие дополнительные поля мы можем отправить в будущих заказах с другими покупателями).

У меня есть образецфайл заказа, который содержит 4 позиции.Все строки 1, 2, 3 имеют другое определенное значение ["required_delivery_date"] = 2018-09-29, а строка 4 имеет другое значение ["required_delivery_date"] = 2018-09-30.

На основекод, я бы ожидал вернуть два заказа, один с позициями 1-3, а другой только с строкой 4. Однако я на самом деле получаю обратно два заказа, один с одной строкой #1, а другой только с позицией № 4.Кажется, что строка

var results = originalLineItems.Where(dynamicWhere, distinctResult);

только когда-либо возвращает единственный результат, когда я запрашиваю словарь, являющийся членом OrderRequestItem.

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

Любая помощь / предложения приветствуются!Имейте в виду, что мне нужно использовать динамический linq, так как я буду постоянно иметь дело с новыми или измененными дополнительными полями в позициях - поэтому возврат к «обычному linq» здесь не вариант.

Ответы [ 2 ]

0 голосов
/ 02 октября 2018

Изменено

dynamicQueryBase.Add("other[\"" + field + "\"]" + " = @" + validFieldCount++);

на

dynamicQueryBase.Add("other[\"" + field + "\"].ToString()" + " = @" + validFieldCount++);

работает как положено.

0 голосов
/ 02 октября 2018

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

var results = originalLineItems.Where(dynamicWhere, distinctResult).ToList();

и проверьте, работает ли он нормально.

...