Re: Mixing linq to sql and linq to xml (in linqpad)

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



Jeroen Mostert wrote:
timor.super@xxxxxxxxx wrote:
Hi group,

In my database, I have a table with fields like this :

id | title | xml
------------------------------------
1 | title1 | <datas><data><item name="item1">value1</
item><item name="item2">value2</item></data></datas>
.....

I would like to filter my xml data, when it contains a item attribute
named item1

I'm using Linqpad with a request like that :

from i in myTable
where
i.xml.Descendants("data").Element("item").Attribute("name").Value ==
"item1"
select i

but, linqpad tells me that :

'System.Collections.Generic.IEnumerable<System.Xml.Linq.XElement>'
does not contain a definition for 'Element' and no extension method
'Element' accepting a first argument of type
'System.Collections.Generic.IEnumerable<System.Xml.Linq.XElement>'
could be found (press F4 to add a using directive or assembly
reference)

It's telling you that "Descendants" will give you a collection of elements, and you're trying to call "Element" on this collection (which only applies to single elements).

This would work:

where i.xml.Descendants("data").Descendants("item").Any(item => (string) item.Attribute("name") == "item1")

So would this (using XPath):

where i.xml.XPathSelectElements("/data/item[@name=\"item1\"]").Any()

....except that neither of these work if "myTable" is an actual SQL table, because LINQ to SQL can't handle XML methods. This is quite unfortunate, because SQL Server 2005 does have support for querying XML. You can get around it by materializing the query results and working with that, of course:

from i in myTable.ToArray()
where i.xml.XPathSelectElements("/data/item[@name=\"item2\"]").Any()
select i

But this has the huge drawback of pulling in all the records for selecting on the client side, which rather defeats the point of querying.

If your table will never become big enough for this to matter, it might be acceptable. Otherwise, you could factor out the XML selection logic to the database. For example:

CREATE FUNCTION dbo.SelectByItemName(@name AS NVARCHAR(MAX))
RETURNS TABLE
RETURN
SELECT id, title, xml FROM myTable
WHERE xml.exist('/datas/data/item[@name=sql:variable("@name")]') = 1;

You can then use LINQ to XML in the designer to create a mapping to this function.

The obvious drawback to this method is that you need to carefully work out your data needs in advance as far as the SQL selection is concerned. And if you can do that, you may want to consider avoiding XML altogether and using a pure relational database, which cooperates much more nicely with most data access technologies.

--
J.
.



Relevant Pages

  • Re: Another idea from pick goes mainstream...
    ... A relational database has nothing to do ... SQL is one of the ... is now considered THE language for any dbms implementing the relational ... Then, XML came out. ...
    (comp.databases.pick)
  • Re: Deviation from object-relational mapping (pySQLFace)
    ... Its goal to separate relational database stuff from algorythmic ... file (XML). ... It provides callable command objects for each sql query. ...
    (comp.lang.python)
  • Is FOR XML EXPLICIT still an accepted technique?
    ... I have inherited an ASP IIS site attached to a SQL ... Server 2000 database. ... I am new at using XML and have done considerable reading. ...
    (microsoft.public.sqlserver.xml)
  • Re: Parsing large amounts of data (200,000 entries) with XML?
    ... since I know the different uses for a database ... and an XML document. ... I didn't invent that either, ... XML and SQL coexist quite nicely. ...
    (microsoft.public.vb.general.discussion)
  • Re: Querying Very Large XML
    ... I was hoping that MSDE (or SQL 2005 Express) might let you get around ... the "we don't want to run a database" argument. ... Yet they provide the same XML ... > XpathDocument at once. ...
    (microsoft.public.dotnet.xml)