5 особенностей SPSiteDataQuery
В SharePoint есть механизм, позволяющий выбирать данные из нескольких списков одним запросом. Для этого существует класс SPSiteDataQuery. Проблема в том, что он имеет ряд особенностей. О них сегодня и речь.
Вступление
Мною уже был написан пост о работе с SPSiteDataQuery в SharePoint 2007. С тех пор мало, что изменилось. Особенности остались.
Два списка для примеров расположены на одном сайте и имеют следующий набор полей:
List1:
- Number (числовой);
- DateOnly (только дата);
- DateTime (дата и время)
- CurrencyUSD (валюта, USD);
- CurrencyRUB (валюта, RUB);
- Lookup (ссылка на List1);
- Lookup2 (ссылка на List1, множественный выбор);
- Calc1 (вычисляемый, [CurrencyUSD]-[CurrencyRUB]).
List2:
- DateOnly (только дата);
- CurrencyEUR (валюта, EUR);
- Lookup (ссылка на List1, множественный выбор);
Картинка (множественный выбор здесь не отражен):
Простой пример
Для начала простой пример, который работает правильно и предсказуемо:
SPSiteDataQuery dataQuery;
dataQuery = new SPSiteDataQuery
{
//Custom List
Lists = @"<Lists ServerTemplate=""100"" />",
// Title only
ViewFields = @"<FieldRef Name=""Title""/>",
// Emptyy query
Query = string.Empty,
Webs = @"<Webs Scope=""SiteCollection"" />"
};
var dt = web.GetSiteData(dataQuery);
Результат:
Поля List, WebId и ID есть всегда.
1. Явно указывать Nullable
Если какое-либо поле отсутствует в списках, из которых извлекаются данные, то необходимо в свойстве ViewFields явно указывать то, что это поле может отсутствовать.
В примере выше изменим свойство ViewFields:
ViewFields = @"<FieldRef Name=""Title"" /><FieldRef Name=""Lookup"" />",
Поле Lookup есть в обоих списках, но оно заполнено не везде и результат будет пустой. Чтобы этого избежать необходимо добавить атрибут Nullable:
ViewFields = @"<FieldRef Name=""Title"" /><FieldRef Name=""Lookup"" Nullable=""TRUE"" />",
Теперь в результирующий набор попадают все строки:
Но при этом все эти поля пустые, не смотря на то, что в списках значения есть!
Отсюда следует вторая особенность:
2. Не использовать множественные lookup'ы
Никогда не используйте lookup-поля с множественным выбором. Данные в этом случае не возвращаются. Это относится ко всем lookup-полям: пользователи и метаданные.
3. Не указывать явно поля ListId, WebId, ID
Если вы вдруг захотите проявить всю свою правильность и указать явно поля ListId, WebId или ID, то ничего хорошего из этого не выйдет. Ожидаемых значений вы не получите.
ViewFields = @"<FieldRef Name='Title' /><FieldRef Name='Id' Nullable='TRUE' /><FieldRef Name='ListId' Nullable='TRUE' /><FieldRef Name='WebId' Nullable='TRUE' />",
Только пустота:
4. Не использовать поля с мета-данными
Не все поля при запросе будут возвращать ожидаемые данные (такие как если бы данные выбирались из списка). Для примера добавим поля ServerUrl и EncodedAbsUrl:
ViewFields = @"<FieldRef Name= 'Title' /><FieldRef Name= 'ServerUrl' Nullable= 'TRUE' /><FieldRef Name= 'EncodedAbsUrl' Nullable= 'TRUE' />"
Результирующий набор содержит данные:
Это тот случай, когда лучше ничего чем правильные данные. То, что возвращает запрос web.GetSiteData() к реальности отношения не имеет. Вот результаты аналогичного запроса List.GetItems():
5. Пользоваться поиском
Если есть необходимость выбирать данные из нескольких списков/библиотек/сайтов/коллекций сайтов, то для этого надо использовать поиск. Работает он крайне быстро и вышеописанных проблем не имеет.