2009-07-09 8 views
6

Comment voulez-vous construire cette requête avec Entity Framework:Entity Framework XML Query

SELECT * 
FROM TreeNodes 
WHERE data.value('(/edumatic/assessmentItem/@type)[1]', 'nvarchar(max)') like 'multiplechoice1' 
colonne de données XML est

. Apparemment, cela est converti en une chaîne par Entity Framework ...

Ceci est mon départ, mais d'ici, je ne sais pas comment ajouter le ... où

var query = from e in edumatic3Context.TreeNodes 
         where e.Data.??????? 
         select e; 

      foreach (var treeNode in query) 
       Console.WriteLine("{0} {1} {2} {3}", treeNode.TreeNodeId, treeNode.Name, treeNode.Type, treeNode.DateChanged); 

J'ai aussi essayé quelque chose comme code suivant mais cela ne fonctionne pas non plus:

var sql = "SELECT VALUE treeNode FROM TreeNodes as treeNode WHERE data.value('(/edumatic/assessmentItem/@type)[1]', 'nvarchar(max)') like 'multiplechoice1'"; 
      var query = edumatic3Context.CreateQuery<TreeNodes>(sql); 

foreach(...) 

Répondre

10

Aucun des langages de requête d'Entity Framework (LINQ to Entities et eSQL) ne prend directement en charge les requêtes XML imbriquées. Donc, vous n'allez pas pouvoir faire ce genre de chose. À moins que vous exécutiez la requête XML après un appel à AsEnumerable(), ce qui est bien sûr quelque peu indésirable du point de vue des performances. Cela dit, vous pouvez probablement écrire une fonction de stockage dans le SSDL qui fait ce filtre pour vous.

Ouvrez le fichier EDMX dans un éditeur XML et essayez d'ajouter un élément dans la section StorageModel (c'est-à-dire le fichier SSDL). Le <CommandText> (je pense que c'est ce que l'on appelle) de cette fonction de stockage est où vous pouvez écrire le T-SQL approprié et vous pouvez également vous référer aux paramètres de la fonction. Désolé, je n'ai pas d'exemple de ce pratique.

Après avoir fait que vous pouvez appeler la fonction de magasin dans eSQL-à-dire quelque chose comme ceci:

SELECT VALUE treeNode FROM TreeNodes as treeNode WHERE 
StorageModelNamespace.MyXmlWrapperFunctionForNVarchar('(/edumatic/assessmentItem/@type)[1]', treeNode.Data) LIKE 'multiplechoice1' 

Dans .NET 4.0 vous serez également en mesure d'écrire une fonction stub dans .NET de sorte que vous pouvez appeler cette fonction en LINQ aussi:

-à-dire

[EdmFunction("StorageModelNamespace", "MyXmlWrapperFunctionForNVarchar"] 
public static string MyXmlHelper(string path, string data) 
{ 
    throw new NotImplementedException("You can only call this function in a LINQ query"); 
} 

alors quelque chose comme ceci:

var query = from e in edumatic3Context.TreeNodes 
      where MyXmlHelper("(/edumatic/assessmentItem/@type)[1]", e.Data) 
       .StartsWith("multiplechoice1") 
      select e; 

S'il vous plaît noter que tout le code ci-dessus est juste pseudo-code Je ne l'ai pas réellement testé, j'essaie juste de vous aider à démarrer.

Hope this helps

Alex

Program Manager Entity Framework équipe

+0

Pouvez-vous recommander un livre pour apprendre Entity Framework (avec des exemples de fonction de magasin ...)? THX. –

+0

Une entrée de blog (qu'Alex a réellement écrit) est très pertinente: http://blogs.msdn.com/alexj/archive/2009/08/07/tip-30-how-to-use-a-custom-store -function.aspx – GordonB

+0

@Alex, j'ai une exigence similaire et j'ai suivi votre suggestion, mais il y a des problèmes à appeler les EdmFunctions dans la condition LINQ Where. Pouvez-vous s'il vous plaît vérifier le poste http://stackoverflow.com/questions/24218403/query-xml-from-sql-using-entity-framework-database-first – Prasad

2

Deux choix:

  1. Ecrire un proc qui renvoie toutes les données requis pour mapper à un type d'entité, et mettez votre SQL là. Cette méthode peut utiliser un index XML sur le serveur de base de données.
  2. Récupérez les données sur le client, puis créez un document XML et utilisez LINQ to XML. Pratique pour le programmeur, mais ne peut pas utiliser un index XML.

LINQ to Entities ne connaît pas les fonctionnalités XML du serveur de base de données.