2009-07-09 17 views
6

¿Cómo construir esta consulta con el marco de la entidad: la columnaEntity Framework consulta XML

SELECT * 
FROM TreeNodes 
WHERE data.value('(/edumatic/assessmentItem/@type)[1]', 'nvarchar(max)') like 'multiplechoice1' 

de datos es XML. Al parecer, esto se convierte en una cadena por el marco de la entidad ...

Ésta es mi comienzo, pero de aquí no sabría cómo agregar el dónde ...

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); 

También probé algo parecido siguiente código pero que no funciona bien:

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(...) 

Respuesta

10

Ninguno de los lenguajes de consulta de Entity Framework (LINQ to Entities y eSQL) admite directamente consultas XML anidadas. Entonces no vas a poder hacer este tipo de cosas. A menos que ejecute la consulta XML después de una llamada al AsEnumerable(), lo cual, por supuesto, es algo indeseable desde una perspectiva de rendimiento.

Habiendo dicho esto, probablemente pueda escribir una función de tienda en el SSDL que hace este filtro por usted.

Abra el archivo EDMX en un editor XML e intente agregar un elemento en la sección StorageModel (es decir, el SSDL). El <CommandText> (creo que así es como se llama) de esa función de almacenamiento es donde puede escribir el T-SQL apropiado y también puede consultar los parámetros de la función. Lo siento, no tengo un ejemplo de esto a mano.

Una vez hecho esto se le puede llamar la función de almacenamiento en eSQL es decir algo como esto:

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

En .NET 4.0 también será capaz de escribir una función ramal en .NET para que pueda llamar a esa función en LINQ también:

es decir

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

entonces algo como esto:

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

Tenga en cuenta que todo el código anterior es solo pseudocódigo. No lo he probado, solo estoy tratando de ayudarlo a comenzar.

Esperanza esto ayuda

Alex

equipo

Gerente del Programa Marco de la entidad

+0

puede recomendar un libro para aprender Entity Framework (con ejemplos de función de almacenamiento ...)? Gracias. –

+0

Una entrada de blog (que Alex realmente escribió) que es bastante relevante: http://blogs.msdn.com/alexj/archive/2009/08/07/tip-30-how-to-use-a-custom-store -function.aspx – GordonB

+0

@Alex, tengo un requisito similar y seguí su sugerencia, pero existen problemas para llamar a EdmFunctions en la condición LINQ Where. ¿Puedes verificar la publicación http://stackoverflow.com/questions/24218403/query-xml-from-sql-using-entity-framework-database-first – Prasad

2

dos opciones:

  1. Escribe un proc que devuelve todos los datos requerido para mapear a un tipo de entidad, y poner su SQL allí. Este método puede usar un índice XML en el servidor de bases de datos.
  2. Recupere los datos en el cliente, luego construya un documento XML y use LINQ to XML. Conveniente para el programador, pero no puede usar un índice XML.

LINQ to Entities no conoce las funciones XML del servidor de bases de datos.