简体   繁体   English

LINQ to SQL可以查询XML字段DB-serverside吗?

[英]Can LINQ to SQL query an XML field DB-serverside?

.NET 3.5, C# .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. 可搜索的一些字段是表中的第一类列,但其中一些实际上是XML数据类型中的嵌套字段。

Previously, I built a system for dynamically constructing the SQL for my search. 以前,我构建了一个系统,用于为我的搜索动态构建SQL。 I had a nice class hierarchy that built SQL expressions and conditional statements. 我有一个很好的类层次结构,它构建了SQL表达式和条件语句。 The only problem was it was not safe from SQL injection attacks. 唯一的问题是SQL注入攻击不安全。

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. 我正在阅读Rob Conery的优秀文章 ,该文章指出,如果永远不会枚举IQueryable结果,那么多个查询可以合并到服务器的单个TSQL查询中。 This got me to thinking that my dynamic search construction was much too complicated - I just needed to combine multiple LINQ expressions. 这让我觉得我的动态搜索结构太复杂了 - 我只需要组合多个LINQ表达式。

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. 我意识到这可能是一个简单的动态查询生成的完美解决方案,可以安全地从SQL注入 - 我只是循环我的IQueryable结果并执行其他条件表达式来获得我的最终单执行表达式。

However, I can't find any support for evaluation of XML data. 但是,我找不到对XML数据评估的任何支持。 In TSQL, to get a value from an XML node, we would do something like 在TSQL中,为了从XML节点获取值,我们会做类似的事情

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

But I can't find the LINQ to SQL equivalent of creating this evaluation. 但我找不到LINQ to SQL等同于创建此评估。 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. 我知道我可以评估所有非XML条件的DB端,然后进行我的XML评估代码方面,但我的数据足够大,A)这是很多网络流量拖累性能和B)我会退出 - 如果我无法评估XML第一个DB端以排除某些结果集,则会出现内存异常。

Ideas? 想法? Suggestions? 建议?

Bonus question - If XML evaluation is in fact possible DB side, what about FLWOR support? 奖金问题 - 如果XML评估实际上是可能的DB方面,那么FLWOR支持呢?

Now that is an interesting question. 现在这是一个有趣的问题。

Right now, you cannot instruct SQL Server to perform XML functions directly from Linq. 目前,您无法指示SQL Server直接从Linq执行XML功能。 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. 但是,您可以让Linq使用用户定义的函数...因此,您可以设置一个udf来处理xml,获取正确的数据等,然后在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). 但是有一个重要的限制:你要查找的XML路径( xmlColumn.value或类似的第一个参数)必须构建到函数中,因为它必须是一个字符串文字 ,它不能从一个字符串构建。输入参数(例如)。 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. 因此,您可以在编写UDF时使用UDF获取您知道的字段,但不能将其作为从XML列获取数据的通用方法。

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. 查看Scott Gutherie关于Linq to SQL的优秀博客系列的支持用户定义函数(UDF)部分,了解有关实现的更多信息。

Hope this helps. 希望这可以帮助。

To clarify Daniel's answer - you cannot use a function to do this unless the XPath part of the query is fixed. 为了澄清Daniel的答案 - 除非修复了查询的XPath部分,否则不能使用函数来执行此操作。 See my blog entry on this: http://conficient.wordpress.com/2008/08/11/linq-to-sql-faq-xml-columns-in-sql/ 请参阅我的博客文章: 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. 基本上你不能通过LINQ to SQL查询xml列。 Although it returns an XElement type you cannot do any SQL translations when trying to filter on this column. 虽然它返回XElement类型,但在尝试对此列进行筛选时,您无法执行任何SQL转换。

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. LINQ to SQL支持使用UDF - 但SQL本身不允许您在XML xpath查询中使用参数字符串 - 它必须是字符串文字。 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. 这意味着如果XPath在设计时被修复,它可以工作,但如果你想能够传递变量XPath语句则不行。

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. 这导致了另外两种替代方法:内联SQL语句(否定了拥有LINQ的价值)和在.NET CLR中编写SQL库函数来执行此操作。

This is not the best, not for all queries, and not completely linq, but works and is fast : 这不是最好的,不适用于所有查询,也不是完全linq,但是工作且速度快:

an xml sql field accept the " .ToString ", so you can do : 一个xml sql字段接受“ .ToString ”,所以你可以这样做:

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 我用它来限制返回的行,然后,我查找每个返回的行

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM