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, множественный выбор);

Картинка (множественный выбор здесь не отражен):

Простой пример

Для начала простой пример, который работает правильно и предсказуемо:

  1. SPSiteDataQuery dataQuery;
  2. dataQuery = new SPSiteDataQuery
  3.     {
  4.         //Custom List
  5.         Lists = @"<Lists ServerTemplate=""100"" />",
  6.         //Title only
  7.         ViewFields = @"<FieldRef Name=""Title""/>",
  8.         // Emptyy query
  9.         Query = string.Empty,
  10.         Webs = @"<Webs Scope=""SiteCollection"" />"
  11.     };
  12. var dt = web.GetSiteData(dataQuery);

Результат:

Поля List, WebId и ID есть всегда.

1. Явно указывать Nullable

Если какое-либо поле отсутствует в списках, из которых извлекаются данные, то необходимо в свойстве ViewFields явно указывать то, что это поле может отсутствовать.

В примере выше изменим свойство ViewFields:

  1. ViewFields = @"<FieldRef Name=""Title"" /><FieldRef Name=""Lookup"" />",

Поле Lookup есть в обоих списках, но оно заполнено не везде и результат будет пустой. Чтобы этого избежать необходимо добавить атрибут Nullable:

  1. ViewFields = @"<FieldRef Name=""Title"" /><FieldRef Name=""Lookup"" Nullable=""TRUE"" />",

Теперь в результирующий набор попадают все строки:

Но при этом все эти поля пустые, не смотря на то, что в списках значения есть!

Отсюда следует вторая особенность:

2. Не использовать множественные lookup'ы

Никогда не используйте lookup-поля с множественным выбором. Данные в этом случае не возвращаются. Это относится ко всем lookup-полям: пользователи и метаданные.

3. Не указывать явно поля ListId, WebId, ID

Если вы вдруг захотите проявить всю свою правильность и указать явно поля ListId, WebId или ID, то ничего хорошего из этого не выйдет. Ожидаемых значений вы не получите.

  1. ViewFields = @"<FieldRef Name='Title' /><FieldRef Name='Id' Nullable='TRUE' /><FieldRef Name='ListId' Nullable='TRUE' /><FieldRef Name='WebId' Nullable='TRUE' />",

Только пустота:

4. Не использовать поля с мета-данными

Не все поля при запросе будут возвращать ожидаемые данные (такие как если бы данные выбирались из списка). Для примера добавим поля ServerUrl и EncodedAbsUrl:

  1. ViewFields = @"<FieldRef Name='Title' /><FieldRef Name='ServerUrl' Nullable='TRUE' /><FieldRef Name='EncodedAbsUrl' Nullable='TRUE' />

Результирующий набор содержит данные:

Это тот случай, когда лучше ничего чем правильные данные. То, что возвращает запрос web.GetSiteData() к реальности отношения не имеет. Вот результаты аналогичного запроса List.GetItems():

5. Пользоваться поиском

Если есть необходимость выбирать данные из нескольких списков/библиотек/сайтов/коллекций сайтов, то для этого надо использовать поиск. Работает он крайне быстро и вышеописанных проблем не имеет.


Поделиться

Коментарии