views:

45

answers:

2

I have simple DAL that consists of a SalesEnquiry object, which includes a List<T> of a Vehicle object, which is used to process incoming enquiries (XML) and write them to a DB. So far so good.

However, I'm writing another app that further processes data in this DB, so I'm wanting to use these same DAL objects to retrieve and manipulate the data.

Rather than returning conventional recordsets and iterating through them, manually populating each property of the SalesEnquiry/Vehicle objects, I thought I could return the data from SQL Server as XML and de-serialise it. I already use this technique to handle the incoming data in the first place.

However, I'm not sure if/how I can construct the appropriate XML in SQL Server or if I must do it in two stages.

The following will extract the enquiries as XML:

Select EnquiryID as 'enquiry/enquiryid',
     EnquiryNo as 'enquiry/enquiryno',
     CompanyName as 'enquiry/company'
From Enquiries e
Where e.EnquiryID = 23
For XML PATH

And the following will extract the associated vehicles as XML:

Select VehicleID as 'vehicle/vehicleid',
    VehicleReg as 'vehicle/vehiclereg'
From Vehicles v
Where v.EnquiryID= 23
For XML PATH

The resulting XML I am after is:

<?xml version="1.0" encoding="utf-8"?>
<enquiry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
  <enquiry_id>123</enquiry_no>
  <enquiry_no>100004</enquiry_no>
  <company>MyCompany</company>
  <enquiry_no>100004</enquiry_no>
  <vehicles>
    <vehicle>
      <vehicle_registration>ABC123</vehicle_registration>
    </vehicle>
    <vehicle>
      <vehicle_registration>XYZ789</vehicle_registration>
    </vehicle>
  </vehicles>
</enquiry>

Can I create this in SQL Server, or must I manually do this in my DAL?

Update:

Following on from Shunty's suggestions, I'm using the following:

Select enquiry.EnquiryID as enquiry_id, enquiry.EnquiryNo, enquiry.CompanyName, VehicleID as [vehicle.vehicle_id], VehicleReg as [vehicle.vehicle_registration]
From Enquiries as enquiry
inner join Vehicles on Vehicles.EnquiryID = enquiry.EnquiryID
Where enquiry.EnquiryID = 23
For XML AUTO, ELEMENTS

..I can get close, but I'm not quite there:

<?xml version="1.0" encoding="utf-8"?>
<enquiry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
  <enquiry_id>123</enquiry_no>
  <enquiry_no>100004</enquiry_no>
  <company>MyCompany</company>
  <enquiry_no>100004</enquiry_no>
    <vehicle>
      <vehicle_registration>ABC123</vehicle_registration>
    </vehicle>
    <vehicle>
      <vehicle_registration>XYZ789</vehicle_registration>
    </vehicle>
</enquiry>

To successfully deserialize, I need my <vehicle> elements to come under a <vehicles> parent element. There must be a way to encourage SQL to craft the right XML...

+1  A: 

Use a standard inner join and then take a look at the AUTO (and ELEMENTS) keywords (on MSDN) for your FOR XML clause. I haven't tried it exactly but it certainly looks to be what you want.

shunty
Thanks Shunty - almost there, but not quite! See my update above. Any idea to add that final parent element?
CJM
I have to confess it looks like it should be path with a nested select but I can't quite get my head round it yet.
shunty
And I see I've been beaten to it. Thank goodness for that - I could see my whole afternoon disappearing :-)
shunty
I thought PATH looked promising at first, but then your suggestion of AUTO almost got me there, before 8kb put me out of my misery. Thanks for your efforts anyway...
CJM
+1  A: 

An alternative using XML PATH:

SELECT
  EnquiryID AS enquiry_id,
  EnquiryNo AS enquiry_no,
  CompanyName AS company,
  (
    SELECT
      VehicleReg AS vehicle_registration
    FROM Vehicles
    WHERE EnquiryID = e.EnquiryID
    FOR XML PATH ('vehicle'), TYPE, ROOT('vehicles')
   )
FROM Enquiries e 
WHERE EnquiryID = 123
FOR XML PATH ('enquiry'), TYPE

Returns:

<enquiry>
  <enquiry_id>123</enquiry_id>
  <enquiry_no>100004</enquiry_no>
  <company>MyCompany</company>
  <vehicles>
    <vehicle>
      <vehicle_registration>ABC123</vehicle_registration>
    </vehicle>
    <vehicle>
      <vehicle_registration>XYZ789</vehicle_registration>
    </vehicle>
  </vehicles>
</enquiry>
8kb
I could kiss you... but I wont. :)I'd looked at Root(), but could figure out how to use it - a subquery didn't occur to me. Thanks.
CJM