Entity Framework consulta XML
-
12-09-2019 - |
Pergunta
Como você construir esta consulta com Entity Framework:
SELECT *
FROM TreeNodes
WHERE data.value('(/edumatic/assessmentItem/@type)[1]', 'nvarchar(max)') like 'multiplechoice1'
coluna de dados é XML. Aparentemente, esta é convertida para uma string pela Entity Framework ...
Este é o meu começo, mas a partir daqui eu não saberia como adicionar o onde ...
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);
Eu também tentei algo como código a seguir, mas que não quer trabalhar:
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(...)
Solução
Nem de linguagens de consulta do Entity Framework (LINQ to Entities e eSQL) apoiar diretamente consultas XML aninhadas. Então você não vai ser capaz de fazer esse tipo de coisa. A menos que você executar a consulta XML após uma chamada para AsEnumerable()
, o que naturalmente é um pouco indesejável do ponto de vista do desempenho.
Dito isto, você provavelmente pode escrever uma função de armazenamento no SSDL que faz esse filtro para você.
Abra o arquivo EDMX-se em um editor XML, e tente adicionar um elemento na seção StorageModel (ou seja, o SSDL). O <CommandText>
(acho que é o que é chamado) dessa função loja é onde você poderia escrever o apropriado T-SQL e você pode se referir a parâmetros da função também. Desculpe eu não tenho um exemplo desta prática.
Depois de ter feito isso você pode chamar a função de armazenamento em eSQL ou seja, algo como isto:
SELECT VALUE treeNode FROM TreeNodes as treeNode WHERE
StorageModelNamespace.MyXmlWrapperFunctionForNVarchar('(/edumatic/assessmentItem/@type)[1]', treeNode.Data) LIKE 'multiplechoice1'
Em .NET 4.0 você também será capaz de escrever uma função ramal em .NET para que possa chamar essa função em LINQ demasiado:
i.
[EdmFunction("StorageModelNamespace", "MyXmlWrapperFunctionForNVarchar"]
public static string MyXmlHelper(string path, string data)
{
throw new NotImplementedException("You can only call this function in a LINQ query");
}
, em seguida, algo como isto:
var query = from e in edumatic3Context.TreeNodes
where MyXmlHelper("(/edumatic/assessmentItem/@type)[1]", e.Data)
.StartsWith("multiplechoice1")
select e;
Por favor, note todo o código acima é apenas pseudo-código que eu realmente não tenho testado-lo, eu só estou tentando ajudá-lo a começar.
Espero que isso ajude
Alex
Program Manager Entity Framework Equipe
Outras dicas
Duas opções:
- Escrever um proc que retorna todos os dados necessários para mapear para um tipo de entidade, e colocar o seu SQL lá. Este método pode utilizar um índice XML no servidor de DB.
- Recuperar os dados no cliente, em seguida, construir um documento XML e uso LINQ to XML. Conveniente para o programador, mas não pode usar um índice XML.
LINQ to Entities não sabe sobre recursos XML servidor de banco de dados.