Запрос Xlinq, возвращающий ноль WhereEnumerableIterator <> - PullRequest
2 голосов
/ 20 февраля 2011

Я пытаюсь выполнить фильтрующий запрос xlinq в c # 4.0, поэтому я могу привязаться к DataContext.код такой:

public IEnumerable<XElement> Filter(int min = 0, int max = int.MaxValue)
{
    IEnumerable<XElement> selected = (
        from x in xmlFile.Elements("Product")
        where (int)x.Element("Price") >= min &&
              (int)x.Element("Price") <= max
        select x);

    return selected;
}

xmlFile - это XElement с загруженным внешним XML-файлом.структура файла xml выглядит примерно так:

<Stock>
    <Product>
      <Name /> 
      <Price /> 
      <Quantity /> 
    </Product>
    ...
</Stock>

Я не получаю никаких ошибок при сборке или запуске, но переменная selected получает только ноль (даже без предложения where).При наведении курсора мыши на переменную во время отладки отображается тип System.Linq.Enumerable.WhereEnumerableIterator.Если я просто верну xmlFile, все будет хорошо, но мне действительно нужно выполнить фильтрацию!


EDIT

, насколько я исследовал, проблема в том, что "Инструкция xmlFile.Elements ("Product") ".Я не знаю, как это объяснить, поэтому я сделал скриншот (в моем коде я на самом деле использую «Respuesto» вместо «Products», я перевел это здесь, чтобы упростить):

(Этоне позволит мне вставить изображение, потому что я новый пользователь, но он здесь: http://i.stack.imgur.com/XTt8r.png

Я использую эту функцию в своем коде как DataContext, например:

gridpricelist.DataContext = Conn.Filter(min: Convert.ToInt32(minprice.Text),
                            max: Convert.ToInt32(maxprice.Text));

minprice и maxprice являются текстовыми полями, и событие KeyUp вызывает функцию сверху


EDIT2

Я понял это, см. Мой ответ. Но я не могу объяснить, почему этоработает таким образом, кто-то может помочь мне понять?

Заранее спасибо!

Ответы [ 3 ]

2 голосов
/ 20 февраля 2011

Если у вас есть «пустые» или «не существующие» ценовые элементы, они сломаются

Попробуйте это:

public static IEnumerable<XElement> Filter(int min = 0, int max = int.MaxValue)
{
    Func<XElement, int?> parse = p => {
        var element = p.Element("Price");

        if (element == null) {
            return null;
        }

        int value;

        if (!Int32.TryParse(element.Value, out value)) {
            return null;
        }

        return value;
    };

    IEnumerable<XElement> selected = (
        from x in xmlFile.Elements("Product")
        let value = parse(x)
        where value >= min &&
            value <= max
        select x);

    return arr;
}
1 голос
/ 21 февраля 2011

Я понял это! Хотя я не знаю, почему подход Xlinq не работает ... вот код, который работал для меня вместо запроса:

    public XElement filter(int min = 0, int max = int.MaxValue)
    {            
        XElement filtered = new XElement("Stock");
        foreach (XElement product in xmlFile.Elements("Product"))
        {
            if ((int)product.Element("Price") >= min &&
                (int)product.Element("Price") <= max)
                    filtered.Add(product);
        }
        return filtered;
    }

было бы здорово, если бы кто-нибудь дал мне объяснение. спасибо за чтение

0 голосов
/ 08 октября 2011

У вас есть две проблемы:

  1. Когда вы зависали над WhereEnumerableIterator и видели, что .Current было null, все работало нормально. Это отложенное выполнение в работе. Некоторые запросы LINQ (это относится и к XLinq) не выполняются, пока вы их не перечислите, поэтому .Current будет null, пока вы его не используете ! Когда вы использовали foreach в своем ответе, он перечислил итератор и выдал значение.

  2. Ваш исходный код не работал, так как он возвращал перечисление XML без корневого элемента, и он появляется независимо от того, какой у вас вызывающий код, он требует наличия корневого элемента. Ваш ответ оборачивает данные в элемент <Stock>. Вы можете использовать свой оригинальный код так:

    public XElement Filter(int min = 0, int max = int.MaxValue)
    {
        var selected = (
            from x in xmlFile.Elements("Product")
            where (int)x.Element("Price") >= min &&
                  (int)x.Element("Price") <= max
            select x);
    
        return new XElement("Stock", selected);
    }
    
...