28 votes

LINQ to SQL peut-il interroger un champ XML côté serveur DB?

.NET 3.5, C#

J'ai une application web avec une fonction de recherche. Certains de ces champs sont consultables sont de première classe de colonnes dans le tableau, mais certains d'entre eux sont en fait des champs imbriqués à l'intérieur d'un type de données XML.

Auparavant, j'ai construit un système dynamique de la construction de la SQL pour ma recherche. J'ai eu une belle hiérarchie de classe qui construit des expressions SQL et les instructions conditionnelles. Le seul problème était qu'il n'était pas sûr d'attaques par injection SQL.

Je lisais Rob Conery l'excellent article (http://blog.wekeroad.com/2008/02/27/creating-in-queries-with-linq-to-sql/), qui a souligné que plusieurs requêtes peuvent être combinées en une seule requête TSQL pour le serveur si le IQueryable résultat n'est jamais énumérés. Cela me fait penser que ma recherche dynamique de la construction a été beaucoup trop compliqué - j'ai juste besoin de combiner plusieurs expressions LINQ.

Par exemple (fictive):

Auteur: ID (int), Nom (varchar(32)), Prénom (varchar(32))

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

Les résultats de la requête suivante:

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

J'ai réalisé que cela pourrait être la solution parfaite pour une simple dynamique de génération de requête, c'est à l'abri de l'injection SQL - je venais en boucle sur mon IQueryable de résultat et d'exécuter d'autres expressions conditionnelles pour obtenir mon dernier single-exécution de l'expression.

Cependant, je ne trouve pas de soutien pour l'évaluation des données XML. En TSQL, pour obtenir une valeur à partir d'un nœud XML, nous ferions quelque chose comme

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

Mais je ne trouve pas le LINQ to SQL équivalent de la création de cette évaluation. N'existe? Je sais que je peux évaluer tous les non-XML conditions DB côté, et puis faire de mon XML évaluations code côté, mais mes données sont suffisamment gros pour qu'Un) c'est beaucoup de trafic réseau à glisser sur la performance et B), je vais sortir-de-la mémoire des exceptions si je ne peux pas évaluer le XML première DB côté pour exclure certains ensembles de résultats.

Des idées? Des Suggestions?

Question Bonus - Si XML de l'évaluation est en effet possible DB côté, qu'en est FLWOR de soutien?

12voto

Daniel M Points 998

Maintenant que c'est une question intéressante.

Droite maintenant, vous ne pouvez pas demander de SQL Server pour exécuter les fonctions XML directement à partir de Linq. Cependant, vous pouvez obtenir Linq pour utiliser les fonctions définies par l'utilisateur... donc, vous pouvez configurer un udf de traiter le xml, obtenir les bonnes données, etc, et ensuite l'utiliser dans votre Linq l'expresion. Ce sera exécutée sur le serveur et doit faire ce que vous voulez.

Découvrez l'Appui des Fonctions Définies par l'Utilisateur (Udf) de la section de Scott Gutherie de l'excellent Blog de la série sur Linq to SQL pour plus d'informations sur la mise en œuvre.

Espérons que cette aide.

4voto

Quango Points 1098

Pour préciser la réponse de Daniel - vous ne pouvez pas utiliser une fonction pour faire cela, à moins que le XPath partie de la requête est fixe. Voir mon billet de blog à ce sujet: http://conficient.wordpress.com/2008/08/11/linq-to-sql-faq-xml-columns-in-sql/

Fondamentalement, vous ne pouvez pas interroger une colonne xml via LINQ to SQL. Bien qu'il renvoie un XElement type de vous ne peut pas faire de SQL traductions en essayant de filtrer sur cette colonne.

LINQ to SQL prend en charge à l'aide de fonctions définies par l'utilisateur - mais SQL elle-même ne vous permettra pas d'utiliser un paramètre de chaîne de caractères dans un fichier XML xpath query - il doit être une chaîne littérale. Cela signifie qu'il peut fonctionner si le XPath est fixé au moment de la conception, mais pas si vous voulez être en mesure de passer une variable d'instruction XPath.

Cela conduit à deux autres moyens de le faire: inline instruction SQL (ce qui annule la valeur d'avoir LINQ) et de l'écriture, en SQL, la fonction de Bibliothèque dans .NET CLR pour ce faire.

-1voto

user1620076 Points 13

Ce n'est pas le meilleur, pas pour toutes les requêtes, et pas complètement linq, mais fonctionne et est rapide:

un champ sql xml accepte le " .ToString ", vous pouvez donc faire:

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

Je l'utilise pour limiter les lignes retournées, puis je recherche chaque ligne retournée

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X