XML-код запроса Entity Framework
-
12-09-2019 - |
Вопрос
Как бы вы построили этот запрос с помощью Entity Framework:
SELECT *
FROM TreeNodes
WHERE data.value('(/edumatic/assessmentItem/@type)[1]', 'nvarchar(max)') like 'multiplechoice1'
столбец данных — XML.По-видимому, это преобразуется в строку с помощью Entity Framework...
Это мое начало, но отсюда я не знаю, как добавить где...
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);
Я также попробовал что-то вроде следующего кода, но это тоже не сработало:
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(...)
Решение
Ни один из языков запросов Entity Framework (LINQ to Entities и eSQL) напрямую не поддерживает вложенные XML-запросы.Так что вы не сможете сделать такого рода вещи.Если вы не запустите XML-запрос после вызова AsEnumerable()
, что, конечно, несколько нежелательно с точки зрения производительности.
Однако вы, вероятно, можете написать функцию сохранения в SSDL, которая сделает этот фильтр за вас.
Откройте файл EDMX в редакторе XML и попробуйте добавить элемент в раздел StorageModel (т.SSDL).А <CommandText>
(Я думаю, именно так она и называется) этой функции хранилища — это место, где вы можете написать соответствующий T-SQL, а также ссылаться на параметры функции.Извините, у меня нет такого удобного примера.
Сделав это, вы можете вызвать функцию Store в eSQL, т.е.что-то вроде этого:
SELECT VALUE treeNode FROM TreeNodes as treeNode WHERE
StorageModelNamespace.MyXmlWrapperFunctionForNVarchar('(/edumatic/assessmentItem/@type)[1]', treeNode.Data) LIKE 'multiplechoice1'
В .NET 4.0 вы также сможете написать функцию-заглушку в .NET, чтобы вы могли вызывать эту функцию и в LINQ:
то есть
[EdmFunction("StorageModelNamespace", "MyXmlWrapperFunctionForNVarchar"]
public static string MyXmlHelper(string path, string data)
{
throw new NotImplementedException("You can only call this function in a LINQ query");
}
тогда что-то вроде этого:
var query = from e in edumatic3Context.TreeNodes
where MyXmlHelper("(/edumatic/assessmentItem/@type)[1]", e.Data)
.StartsWith("multiplechoice1")
select e;
Обратите внимание, что весь приведенный выше код — это всего лишь псевдокод. На самом деле я его не проверял, я просто пытаюсь помочь вам начать работу.
Надеюсь это поможет
Алекс
Менеджер программы Entity Framework Team
Другие советы
Два варианта:
- Напишите процедуру, которая возвращает все данные, необходимые для сопоставления с типом сущности, и поместите туда свой SQL.Этот метод может использовать индекс XML на сервере БД.
- Получите данные на клиенте, затем создайте XML-документ и используйте LINQ to XML.Удобен для программиста, но не может использовать XML-индекс.
LINQ to Entities не знает о функциях XML сервера БД.