Reputation: 147
I'm new to linq and I'm having trouble writing a query that pulls back the data I'm looking for. The xml file has orders, each order has purchase order info and products, each prouct has its own elements and descendants. I need to query all the orders and their descendants into one colletion but for some reason the linq query syntax is very counter-intuitive to me.
Here's a truncated sample of my xml
<fulfillment>
<orders>
<order>
<isbulk>true</isbulk>
<purchaseorder>
<id>Acme Inustries</id>
<quantity>15</quantity>
</purchaseorder>
<items>
<item>
<prods>
<prod>
<seq>1</seq>
<issuetype>NEW</issuetype>
<loop>
<proxy>xyz123</proxy>
<servicecode>55</servicecode>
</loop>
</prod>
<prod>
<seq>2</seq>
<issuetype>NEW</issuetype>
<loop>
<proxy>abc987</proxy>
<servicecode>121</servicecode>
</loop>
</prod>
</prods>
</item>
</items>
</order>
<order>
<isbulk>true</isbulk>
<purchaseorder>
<id>ABC Co</id>
<quantity>10</quantity>
</purchaseorder>
<items>
<item>
<prods>
<prod>
<seq>1</seq>
<issuetype>NEW</issuetype>
<loop>
<proxy>xyz456</proxy>
<servicecode>998</servicecode>
</loop>
</prod>
<prod>
<seq>2</seq>
<issuetype>NEW</issuetype>
<loop>
<proxy>abc654</proxy>
<servicecode>664</servicecode>
</loop>
</prod>
</prods>
</item>
</items>
</order>
</orders>
</fulfillment>
My objects look a bit like this:
public class order
{
public bool IsBulk { get; set; }
public PurchaseOrder PurchaseOrder = new PurchaseOrder();
public List<prod> ListOfProds = new List<prod>();
}
public class prod
{
public string Seq { get; set; }
public string IssueType { get; set; }
public string Proxy { get; set; }
public string ServiceCode { get; set; }
}
public class PurchaseOrder
{
public string ID { get; set; }
public string Quantity { get; set; }
}
So I've been working on a query for the best part of a day and just can't seem to get it right. Here's what I've got so far:
List<order> orderlist = new List<order>();
XDocument xmlDoc = XDocument.Load(FilePath);
var list = (from myOrder in xmlDoc.Descendants("order")
select new
{
linq_orderIsBulk = Convert.ToBoolean(myOrder.Element("isbulk").Value),
linq_purchaseOrderID = myOrder.Element("purchaseorder").Element("id").Value,
linq_purchaseOrderQuantity = myOrder.Element("purchaseorder").Element("quantity").Value,
prodlist = myOrder.Element("items").Element("item").Element("prods").Elements("prod").Select(e => new
{
Linq_seq = e.Element("seq").Value,
Linq_IssueType = e.Element("issuetype").Value,
Linq_proxy = e.Element("loop").Element("proxy").Value,
Linq_serviceCode = e.Element("loop").Element("servicecode").Value
}).ToList()
});
//do code to put the collection in list into List orderlist
But when I do this, I seem to end up getting an "Object reference not set to an instance of an object." error on the subquery. When I comment out the Linq_proxy and Linq_serviceCode lines, I get results but not the right ones. When I loop through list and grab a single order then look at the prodlist for that order, the count is the total amount of prods for that file (4) instead of the 2 for that order. Any thoughts?
Upvotes: 0
Views: 115
Reputation: 78920
I just ran this, and it works fine:
var orders = new List<order>(
from myOrder in xmlDoc.Descendants("order")
let purchaseOrder = myOrder.Element("purchaseorder")
select new order {
IsBulk = Convert.ToBoolean(myOrder.Element("isbulk").Value),
PurchaseOrder = new PurchaseOrder {
ID = purchaseOrder.Element("id").Value,
Quantity = purchaseOrder.Element("quantity").Value
},
ListOfProds = new List<prod>(
from product in myOrder.Descendants("prod")
let loop = product.Element("loop")
select new prod
{
Seq = product.Element("seq").Value,
IssueType = product.Element("issuetype").Value,
Proxy = loop.Element("proxy").Value,
ServiceCode = loop.Element("servicecode").Value
}
)
}
);
Notice that you can project a collection directly into objects of your type, so you don't have to have code later on to create your orders collection.
Upvotes: 3