Can LINQ to SQL query an XML field DB-serverside?
Asked Answered
G

3

28

.NET 3.5, C#

I have a web app with a "search" feature. Some of the fields that are searchable are first-class columns in the table, but some of them are in fact nested fields inside an XML data type.

Previously, I built a system for dynamically constructing the SQL for my search. I had a nice class hierarchy that built SQL expressions and conditional statements. The only problem was it was not safe from SQL injection attacks.

I was reading Rob Conery's excellent article which pointed out that multiple queries can combined into a single TSQL query for the server if the IQueryable result is never enumerated. This got me to thinking that my dynamic search construction was much too complicated - I just needed to combine multiple LINQ expressions.

For example (contrived):

Author:
    ID (int),
    LastName (varchar(32)), 
    FirstName (varchar(32))

    context.Author.Where(xx => xx.LastName == "Smith").Where(xx => xx.FirstName == "John")

Results in the following query:

SELECT [t0].[ID], [t0].[LastName], [t0].[FirstName]
FROM [dbo].[Author] AS [t0]
WHERE ([t0].[LastName] = Smith) AND ([t0].[FirstName] = John)

I realized this might be the perfect solution for a simple dynamic query generation that's safe from SQL injection - I'd just loop over my IQueryable result and execute additional conditionals expressions to get my final single-execution expression.

However, I can't find any support for evaluation of XML data. In TSQL, to get a value from an XML node, we would do something like

XMLField.value('(*:Root/*:CreatedAt)[1]', 'datetime') = getdate() 

But I can't find the LINQ to SQL equivalent of creating this evaluation. Does one exist? I know I can evaluate all non-XML conditions DB side, and then do my XML evaluations code side, but my data are large enough that A) that's a lot of network traffic to drag on performance and B) I'll get out-of-memory exceptions if I can't evaluate the XML first DB side to exclude certain result sets.

Ideas? Suggestions?

Bonus question - If XML evaluation is in fact possible DB side, what about FLWOR support?

Groveman answered 11/11, 2008 at 22:41 Comment(3)
It's the end of 2013 - any updates?Noise
@BenjaminGruenbaum It has been a long time since I have thought about this question. My use case for it disappeared when I changed jobs between then and now. Best as I can recall, I used the approach DanialM recommended below, which was to make a call to a user-defined function. Can't say as I've noticed any direct support in LINQ since then (but I haven't been looking either)Groveman
Interesting - I'll try to fish new answers 5 years later with a bounty.Noise
S
12

Now that is an interesting question.

Right now, you cannot instruct SQL Server to perform XML functions directly from Linq. However, you can get Linq to use user defined functions... so, you could setup a udf to process the xml, get the right data, etc, and then use that in your Linq expresion. This will execute on the server and should do what you want. There's an important limitation, though: The XML path you're looking for (the first parameter to xmlColumn.value or similar) has to be built into the function because it has to be a string literal, it can't be built from an input parameter (for instance). So you can use UDFs for getting fields you know about when writing the UDF, but not as a general-purpose way to get data from XML columns.

Check out the Supporting User Defined Functions (UDFs) section of Scott Gutherie's excellent Blog series on Linq to SQL for more info on implementation.

Hope this helps.

Scevo answered 11/11, 2008 at 23:32 Comment(1)
Thanks Daniel, that did the trick! I had read that article a while back, but it didn't click with me when I read the article I mentioned above about combining multiple queries together before execution.Groveman
G
4

To clarify Daniel's answer - you cannot use a function to do this unless the XPath part of the query is fixed. See my blog entry on this: http://conficient.wordpress.com/2008/08/11/linq-to-sql-faq-xml-columns-in-sql/

Basically you cannot query an xml column via LINQ to SQL. Although it returns an XElement type you cannot do any SQL translations when trying to filter on this column.

LINQ to SQL does support using UDFs - but SQL itself will not allow you to use a parameter string in a XML xpath query - it has to be a string literal. That means it can work if the XPath is fixed at design time, but not if you wanted to be able to pass a variable XPath statement.

This leads to only two other alternative ways of doing it: inline SQL statement (which negates the value of having LINQ) and writing a SQL Library function in .NET CLR to do this.

Glacial answered 14/12, 2008 at 12:0 Comment(2)
See also an update on that blog: conficient.wordpress.com/2011/01/20/…Grandpapa
The best way to clarify an answer is to do just that: Edit the answer to clarify it, or if you didn't (at that time) have editing rights, comment to flag up the issue. (Was that how SO worked back in Dec '08? I have no idea, I joined eight months later. :-) It was when I joined, but SO was growing and changing rapidly at the time.)Makell
B
-1

This is not the best, not for all queries, and not completely linq, but works and is fast :

an xml sql field accept the ".ToString", so you can do :

Dim txt as String = "<File>3</File>"
Return (From P In DC.LPlanningRefs Where P.Details.ToString.Contains(txt) Select P).FirstOrDefault

I use it to limit lines returned, and then, I look for each returned lines

Burkhalter answered 21/5, 2014 at 9:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.