Link blog.vitalyzhukov.ru

Блог переехал вот сюда: Blog.VitalyZhukov.ru

15 мар. 2011 г.

Linq to Sharepoint. Особенности

В SharePoint 2010 появилась замечательная вещь под названием Linq-to-SharePoint. Не без особенностей конечно. Вот некоторые из тех, что я "нашел":



1. First() / FirstOrDefault()
Те, кто работал с Linq-to-SQL или Entity Framework, знают, что запрос вида:

using (var ctx = new HRDataContext(webUrl))

{
    var emps = ctx.EmployeeCollection.First(e => e.Id == id);
}
равнозначен запросу:

using (var ctx = new HRDataContext(webUrl))
{
    var emps = ctx.EmployeeCollection.Where(e => e.Id == id).First();
}

Вот только это не работает в SharePoint'е. Там этот запрос равнозначен следующему:

using (var ctx = new HRDataContext(webUrl))

{
    var emps = ctx.EmployeeCollection.ToList().Where(e => e.Id == id).First();
}
Если тестировать приложение на 10-20 записях в списке, то можно не заметить падения производительности. Такая бага может проявить себя далеко после сдачи решения заказчику.

Вывод: не использовать .First(<filter>) без предварительной фильтрации.

2. Аналог TSQL-оператора IN
В Linq-To-SharePoint его нет, поэтому выражения вида:
using (var ctx = new HRDataContext(_webUrl))

{
    var vipIds = new [] { 1, 5, 9, 23, 57, 198, 345);
    var emps = ctx.EmployeeCollection.Where(e => vipIds.Contains(e.Id));
}
работать не будут. Вместо этого произойдет исключение. А чтобы его не было надо явно выгружать данные из списка в память (например .ToList()) и только потом использовать .Contains().

Вывод: использовать .Contains() только над коллекциями в памяти

3. Выбор данных из папки
По умолчанию Linq-to-SharePoint выбирает элементы списка/библиотеки только из корневого каталога. Чтобы заставить его вытащить данные из дочерних папок или из какой-то конкретной папки надо использовать метод .ScopeToFolder(rootFolder, recursiveFlag), где
rootFolder - папка, из которой выбираем данные (для корневой папки можно передать string.Empty;
recursiveFlag - флаг, определяющий просмотр дочерних папок (флаг поднят - смотрим, опущен - не обращаем внимание на дочерние папки)

Используем примерно так:
using (var ctx = new HRDataContext(_webUrl))

{
    string.Empty
    var emps = ctx.EmployeeCollection.ScopeToFolder(string.Empty);
}


Я рекомендовал бы при разработке сразу учитывать эту особенность и не ждать, пока пользователи начнут строить структуру папок внутри списка и удивляться, что система работает странновато.

Вывод: планировать возможность создания папок в списках/библиотеках и учитывать это при разработке

4. Сохранение элемента в папке списка/библиотеки

Данные из папки выбирать научились, теперь надо бы уметь и сохранять/создавать элемент в папке.
Для этого просто указываем путь к папке в свойстве Path элемента. Примерно вот так:
var query = ctx.DocumentCardCollection.ScopeToFolder(string.Empty, true)

               .Where(d => d.Date >= DateTime.Today.AddDays(-5));
var card = query.First();
card.Path = "/WebUrl/ListUrl/Folder1/SubFolder2";

Вывод: см. вывод в п.3

Пользуемся на здоровье и покоряем сердца заказчиков


Комментариев нет:

Отправить комментарий