Linq to SharePoint. Получение данных из другой коллекции сайтов

Сегодня я покажу как выполнять Cross-SiteCollection запросы с использованием Linq to SharePoint.

По умолчанию, Linq to SharePoint работает только в пределах одной коллекции узлов (SPSite). Это ограничение связано с объектом SPServerDataConnection, предоставляющего в Linq to SharePoint подключение к спискам/библиотекам документов. Если конкретней, то проблема в конструкторе:

  1. public SPServerDataConnection(string url)
  2. {
  3.     if (SPContext.Current != null)
  4.     {
  5.         this.defaultSite = SPContext.Current.Site;
  6.         this.defaultWeb = (SPContext.Current.Web.Url == url) 
  7.             ? SPContext.Current.Web 
  8.             : this.defaultSite.OpenWeb(new Uri(url).PathAndQuery);
  9.     }
  10.     else
  11.     {
  12.         this.defaultSite = new SPSite(url);
  13.         this.defaultWeb = this.defaultSite.OpenWeb(new Uri(url).PathAndQuery);
  14.     }
  15.     if (!this.defaultWeb.Exists)
  16.     {
  17.         throw new ArgumentException(Resources.GetString("CannotFindWeb",
  18.                           new object[] { url }));
  19.     }
  20.     this.defaultWebUrl = this.defaultWeb.ServerRelativeUrl;
  21.     this.openedWebs = new Dictionary<string, SPWeb>();
  22.     this.openedWebs.Add(this.defaultWebUrl, this.defaultWeb);
  23. }

Т.е. если SPContext доступен, то за пределы коллекции сайтов "выйти" нельзя. Трюк, позволяющий обойти это ограничение аналогичен трюку при работе с Linq to SharePoint в анонимном режиме.

Нам необходимо обнулить текущий контекст, чтобы спровоцировать SharePoint создать новый объект SPSite.

Cross-SiteCollection Repository

Инкапсулировать CrossSiteCollection-запросы в репозиторий можно следующим образом: сделать новый конструктор, который принимает булево значение - флаг, отвечающий за инициализацию контекста для другой коллекции сайтов.

  1. protected BaseRepository(string listName, string webUrl, bool readOnly, bool crossSite)
  2. {
  3.     ReadOnly = readOnly;
  4.     ListName = listName;
  5.     WebUrl = webUrl;
  6.  
  7.     var ctx = SPContext.Current;
  8.     IsAnonymous = ctx != null && SPContext.Current.Web.CurrentUser == null;
  9.     if (crossSite)
  10.     {
  11.         var backupCtx = HttpContext.Current;
  12.         // Сбрасываем контекст
  13.         HttpContext.Current = null;
  14.         // Инициализируем контекст и прочее
  15.         InitializeParameters();
  16.         HttpContext.Current = backupCtx;
  17.     }
  18.     else
  19.     {
  20.         InitializeParameters();
  21.     }
  22. }

Применение

В демонстрационном проекте я создал веб-часть CrossSiteCollectionDataQuery, демонстрирующую работу с данными, расположенными в другой коллекции сайтов. Код метода CreateChildControls в нем выглядит вот так (частично):

  1. // Другая коллекция сайтов
  2. var repository1 = new EmployeeRepository("http://SharePointServer/linq"truetrue);
  3. var items1 = repository1.GetEntityCollection();
  4. foreach (var employee in items1)
  5. {
  6.     // Выводим информацию о сотруднике
  7.     RenderEmployeeInfo(employee);
  8. }
  9. Controls.Add(new LiteralControl("***<br/>"));
  10. // Текущая коллекция сайтов
  11. var repository2 = new EmployeeRepository("http://SharePointServer/sites/asc"truefalse);
  12. var items2 = repository2.GetEntityCollection();
  13. foreach (var employee in items2)
  14. {
  15.     // Выводим информацию о сотруднике
  16.     RenderEmployeeInfo(employee);
  17. }

И результат работы:

Виталий Жуков

Виталий Жуков

SharePoint архитектор, разработчик, тренер, Microsoft MVP (Office Development). Более 15 лет опыта работы с SharePoint, Dynamics CRM, Office 365, и другими продуктами и сервисами Microsoft.

Смотрите также

EntityFramework. Оптимистические блокировки

EntityFramework. Оптимистические блокировки

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

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

SharePoint 2010. Настройка входящей почты для кастомного списка

SharePoint 2010. Настройка входящей почты для кастомного списка

SharePoint 2010. PeopleEditor. Установка значения

SharePoint 2010. PeopleEditor. Установка значения

Linq to SharePoint. Особенности. Часть 2

Linq to SharePoint. Особенности. Часть 2