Подтвердить что ты не робот

Может ли LINQ to SQL запрашивать XML-сервер DB-serveride?

.NET 3.5, С#

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

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

Я читал превосходную статью Роба Конери (http://blog.wekeroad.com/2008/02/27/creating-in-queries-with-linq-to-sql/), в которой указывалось, что несколько запросов могут объединяться в один TSQL-запрос для сервер, если результат IQueryable никогда не перечислит. Это заставило меня думать, что моя динамическая конструкция поиска слишком сложна - мне просто нужно объединить несколько выражений LINQ.

Например (изобретенный):

Автор:   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 node, мы сделали бы что-то вроде

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

Чтобы пояснить ответ Даниэля - вы не можете использовать функцию для этого, если не будет исправлена ​​часть запроса 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 Library в .NET CLR для этого.

Ответ 3

Это не самое лучшее, а не для всех запросов, а не полностью 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

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