2013-03-28 2 views
0

Возможно, я ошибаюсь, написав правильный код или задающий вопрос, но я ищу помощь в следующем.xml many to many join using linq

У меня есть файл XML с многие ко многим следующим образом:

<ShowRoom> 
    <Cars> 
    <Car id="1" number="001" name="MyCar" > 
     <Parts> 
     <Part id="1" /> 
     <Part id="2" /> 
     </Parts> 
    </Car> 
    <Car id="2" number="002" name="YourCar" > 
     <Parts> 
     <Part id="2" /> 
     <Part id="3" /> 
     <Part id="4" /> 
     </Parts> 
    </Car> 
    </Cars> 
    <Parts> 
    <Part id="1" name="Tyre" active="true"/> 
    <Part id="2" name="Window" active="true"/> 
    </Parts> 
</ShowRoom> 

В соответствии с этим объектом является следовать

public class Car 
{ 
    private int _id; 
    public int Id 
    { 
     get { return _id; } 
     set { _id = value; } 
    } 

    private string _number; 
    public string Number 
    { 
     get { return _number; } 
     set { _number = value; } 
    } 

    private string _name; 
    public string Name 
    { 
     get { return _name; } 
     set { _name = value; } 
    } 

    private List<Parts> _listParts; 
    public List<Parts> ListParts 
    { 
     get { return _listParts; } 
     set { _listParts = value; } 
    } 
} 

То, что я пытаюсь это прочитать XML и соединение между автомобилем и детали, поэтому я получу предмет автомобиля со всеми их деталями.

IEnumerable<XElement> xCar = xdoc.Element("ShowRoom").Element("Cars").Elements("Car"); 
       IEnumerable<XElement> xPart = xdoc.Element("ShowRoom").Element("Parts").Elements("Part"); 
       IEnumerable<Car> car = xCar.Join(
        xPart, 
        c => c.Element("Parts").Element("Part").Attribute("id").Value, 
        p => p.Attribute("id").Value, 
        (c, p) => 
        new Cars 
        { 
         Id = int.Parse(c.Attribute("id").Value), 
         Number = (string)c.Attribute("number").Value, 
         Name = (string)c.Attribute("name").Value, 

         ListParts = 
         { 
           new Parts 
            { 
             Id = int.Parse(p.Attribute("id").Value), 
             Name = (string)p.Attribute("name").Value, 
             Active = bool.Parse(p.Attribute("active").Value) 
            } 
         } 
        }); 

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

     ListParts = 
         { 
           new Parts 
            { 
             Id = int.Parse(p.Attribute("id").Value), 
             Name = (string)p.Attribute("name").Value, 
             Active = bool.Parse(p.Attribute("active").Value) 
            } 

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

Спасибо.

+0

Просто укажите, зачем устанавливать частные свойства при создании общедоступных методов, которые позволяют обозревателю одновременно получать и устанавливать эти свойства, вы должны просто оставить их общедоступными, если вы намерены разрешить вызывающему абоненту выполнять get & set , – Derek

+0

@JonSkeet извиняется, если я запутал вещи. – Derek

ответ

2

Я настоятельно рекомендую строить словарь частей, затем наращивая список автомобилей:

Dictionary<int, Part> partsById = doc.Root 
    .Element("Parts") 
    .Elements("Part") 
    .Select(p => new Parts 
      { 
       Id = (int) p.Attribute("id"), 
       Name = (string) p.Attribute("name"), 
       Active = (bool) p.Attribute("active") 
      }) 
    .ToDictionary(part => part.Id); 

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

Затем, когда вы строите свой список автомобилей, вы можете использовать:

... 
ListParts = c.Element("Parts") 
      .Elements("Part") 
      .Select(p => partsById[(int) p.Attribute("Id")]) 
      .ToList(); 

Вы также должны изучить автоматически реализованы свойства, которые позволили бы сократить свой Car класс всего несколько строк кода:

public class Car 
{ 
    public int Id { get; set; } 
    public string Number { get; set; } 
    public string Name { get; set; } 
    public List<Parts> ListParts { get; set; } 
} 
+0

Спасибо, Джон Скит, его изумительный. Я не могу голосовать, так как это требует некоторой репутации. Спасибо Derek за ваши отзывы. – toughcanny

+0

@JonSkeet Извинения, если я вызвал путаницу, я предлагаю, чтобы ваш класс выглядел так, как у Джона есть его набор здесь, вот и все. – Derek

+0

@Derek: Стоит понять, что это * абсолютно эквивалентно * оригинальному коду плаката. У него все еще есть частные поля и общественные объекты. На этом фронте ничего не изменилось - это просто более простое представление источника. –