LINQ to XML с помощью join и GroupBy (). Это правильно? - PullRequest
0 голосов
/ 07 января 2010

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

Узел propertyAuto представляет автомобиль с id = 606. Этот узел должен иметь как минимум два дочерних узла propertyValue, один из которых ссылается на элемент vehicleValuation с атрибутом «Book», а другой - «Auto». (Мой код еще не проверяет, они оба могут быть Авто или Забронировать сейчас)

Наконец, мне нужно получить балансовую стоимость и стоимость авто для той же машины.

Обратите внимание, что я никогда не узнаю ни ID, ни idRef заранее, и в будущем будет несколько машин.

Вот мой код (готов к копированию в LINQPad!)

var data = XElement.Parse (@"
<MyXML>
  <propertyAuto id='606'>
    <Values>
      <propertyValue idRef='f95d5dce-8152-4e9e-889e-7433d32664d6' />
      <propertyValue idRef='cd1a83a7-dd04-41f9-b31c-5408a38ac777' />
    </Values>
  </propertyAuto>
  <Valuations>
    <vehicleValuation id='cd1a83a7-dd04-41f9-b31c-5408a38ac777'
    valuationType='Auto' estimatedValue='8350.00' />
    <vehicleValuation id='f95d5dce-8152-4e9e-889e-7433d32664d6'
    valuationType='Book' estimatedValue='12475.00' />
  </Valuations>
</MyXML>");

var valuations = from property in data.Descendants("propertyValue")
                 join value in data.Descendants("vehicleValuation")
                 on
                    (string)property.Attribute("idRef")
                 equals
                    (string)value.Attribute("id")
                 where property.Parent.Descendants("propertyValue").Count() > 1
                 && ((string)value.Attribute("valuationType") == "Auto" || (string)value.Attribute("valuationType") == "Book")               
                 select new { Value = value.Attribute("estimatedValue").Value, Type = value.Attribute("valuationType").Value, PropertyID = property.Parent.Parent.Attribute("id").Value };

valuations.Dump();

var values = valuations.GroupBy(x=> x.PropertyID).FirstOrDefault();
string auto = values.Where(x => x.Type == "Auto").Select(x=>x.Value).First().ToString();
string book = values.Where(x => x.Type == "Book").Select(x=>x.Value).First().ToString();

auto.Dump();
book.Dump();

Это работоспособно или я должен перейти на xpath и т. Д.?

Ответы [ 2 ]

1 голос
/ 07 января 2010

Очевидно, что ваше решение работоспособно, потому что оно работает! Я бы также взял немного дальше, чтобы получить результаты в виде списка автомобилей со свойствами, которые вы можете легко проверить:

var carProperties = from propertyAuto in data.Descendants("propertyAuto")
                    select new
                    {
                        Id = propertyAuto.Attributes("id").First().Value,
                        Properties = from property in propertyAuto.Descendants("propertyValue")
                                     join value in data.Descendants("vehicleValuation")
                                     on property.Attribute("idRef").Value
                                     equals value.Attribute("id").Value
                                     select new
                                     {
                                         Value = value.Attribute("estimatedValue").Value,
                                         Type = value.Attribute("valuationType").Value,
                                         PropertyID = property.Parent.Parent.Attribute("id").Value
                                     }
                    };

var cars = from car in carProperties
           select new
           {
               Id = car.Id,
               Auto = car.Properties.Where(x => x.Type == "Auto").Select(x => x.Value).First(),
               Book = car.Properties.Where(x => x.Type == "Book").Select(x => x.Value).First()
           };

Обратите внимание, что GroupBy больше не нужен.

1 голос
/ 07 января 2010
 var valuations = el.Element("Valuations").Elements("vehicleValuation");
 var carNodes = el.Elements("propertyAuto");
 var cars = carNodes.Select(x => 
                new {
                     id = x.Attribute("id").Value,
                     PropertyValues = x.Element("Values").Elements("propertyValue").
                                        SelectMany(
                                                y => valuations.Where( 
                                                        val => val.Attribute("id").Value == y.Attribute("idRef").Value
                                                                      ).Select( valuation => 
                                                                          new { 
                                                                                Type = valuation.Attribute("valuationType"),
                                                                                EstVal = valuation.Attribute("estimatedValue")
                                                                              }
                                                                              )
                                               )
                     });

Немного сложно, но это создаст анонимный тип, у которого идентификаторы автомобилей соответствуют значениям свойств.

Если вы хотите, чтобы автомобили Auto и Book оценивали напрямую, вы можете сделать что-то вроде этого.

var cars = carNodes.Select(car => 
                new {
                     id = car.Attribute("id").Value,
                     Auto = car.Element("Values").Elements("propertyValue").
                                        SelectMany(
                                                y => valuations.Where( 
                                                        val => val.Attribute("id").Value == y.Attribute("idRef").Value &&
                                                               val.Attribute("valuationType").Value == "Auto"
                                                                      )
                                                                .Select( valuation => valuation.Attribute("estimatedValue"))
                                               ).SingleOrDefault(),
                     Book = car.Element("Values").Elements("propertyValue").
                                          SelectMany(
                                                  y => valuations.Where(
                                                          val => val.Attribute("id").Value == y.Attribute("idRef").Value &&
                                                                 val.Attribute("valuationType").Value == "Book"
                                                                        )
                                                                  .Select(valuation => valuation.Attribute("estimatedValue"))
                                                 ).SingleOrDefault(),
                     });
...