Может ли LINQ to SQL запрашивать XML-поле DB-serveride? - PullRequest
28 голосов
/ 12 ноября 2008

.NET 3.5, C #

У меня есть веб-приложение с функцией поиска. Некоторые из доступных для поиска полей являются столбцами первого класса в таблице, но некоторые из них фактически являются вложенными полями внутри типа данных XML.

Ранее я построил систему для динамического построения SQL для моего поиска. У меня была хорошая иерархия классов, которая строила выражения SQL и условные операторы. Единственная проблема заключалась в том, что он не был защищен от атак SQL-инъекций.

Я читал Отличная статья Роба Конери , в которой указывалось, что несколько запросов могут объединяться в один запрос TSQL для сервера, если результат IQueryable никогда не перечисляется. Это заставило меня задуматься о том, что моя конструкция динамического поиска была слишком сложной - мне просто нужно было объединить несколько выражений LINQ.

Например (надумано):

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

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

Результаты в следующем запросе:

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

Я понял, что это может быть идеальным решением для генерации простых динамических запросов, защищенных от SQL-инъекций - я просто зациклился на своем результате IQueryable и выполнил дополнительные условные выражения, чтобы получить мое окончательное выражение для одного выполнения.

Однако я не могу найти никакой поддержки для оценки данных XML. В TSQL, чтобы получить значение из узла XML, мы бы сделали что-то вроде

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

Но я не могу найти эквивалент LINQ to SQL для создания этой оценки. Один существует? Я знаю, что могу оценить все стороны БД, не относящиеся к условиям XML, а затем выполнить код кода для оценки XML, но мои данные достаточно велики, чтобы А) это много сетевого трафика, чтобы снизить производительность, и Б) исключений памяти, если я не могу оценить первую сторону БД XML для исключения определенных наборов результатов.

Идеи? Предложения?

Бонусный вопрос - Если оценка XML действительно возможна на стороне БД, как насчет поддержки FLWOR?

Ответы [ 3 ]

12 голосов
/ 12 ноября 2008

Теперь это интересный вопрос.

В настоящее время вы не можете указать SQL Server выполнять функции XML непосредственно из Linq. Однако вы можете заставить Linq использовать пользовательские функции ... Таким образом, вы можете настроить udf для обработки xml, получить правильные данные и т. д., а затем использовать это в своем выражении Linq. Это будет выполняться на сервере и должно делать то, что вы хотите. Однако есть важное ограничение: искомый путь XML (первый параметр к xmlColumn.value или подобный) должен быть встроен в функцию, потому что это должна быть строка литерал , он может не может быть построен из входного параметра (например). Таким образом, вы можете использовать UDF для получения полей, о которых вы знаете, когда пишете UDF, но не как универсальный способ получения данных из столбцов XML.

Посмотрите раздел Поддержка пользовательских функций (UDF) Отличная серия блогов Скотта Гатери о Linq to SQL для получения дополнительной информации о реализации.

Надеюсь, это поможет.

4 голосов
/ 14 декабря 2008

Чтобы прояснить ответ Даниэля - вы не можете использовать функцию, чтобы сделать это, если часть запроса XPath не исправлена. Смотрите мою запись в блоге по этому вопросу: http://conficient.wordpress.com/2008/08/11/linq-to-sql-faq-xml-columns-in-sql/

Как правило, вы не можете запросить столбец xml через LINQ to SQL. Хотя он возвращает тип XElement, вы не можете выполнять какие-либо переводы SQL при попытке фильтрации по этому столбцу.

LINQ to SQL поддерживает использование UDF - но сам SQL не позволяет использовать строку параметра в запросе XML xpath - это должен быть строковый литерал. Это означает, что он может работать, если XPath исправлен во время разработки, но не если вы хотите иметь возможность передавать переменную инструкцию XPath.

Это приводит только к двум другим альтернативным способам сделать это: встроенный оператор SQL (который сводит на нет значение наличия LINQ) и написание функции библиотеки SQL в .NET CLR для этого.

0 голосов
/ 21 мая 2014

Это не лучший, не для всех запросов и не полностью linq, но работает и быстро:

поле 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

Я использую его для ограничения возвращаемых строк, а затем я ищу каждую возвращаемую строку

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...