2015-03-18 2 views
0

фона:Как загрузить списки SharePoint из любого места в семействе сайтов с помощью TemplateID с помощью CSOM?

Я пытаюсь создать C# командной строки утилита для извлечения списка информации о товарах из списков, которые могут существовать в любом месте в пределах определенного семейства сайтов. Все списки, которые я пытаюсь извлечь из, были созданы из определенного шаблона с идентификатором 10003 (Пользовательский шаблон).

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

У меня есть семейство сайтов с 7 непосредственными детьми и ~ 200 общих суб-сайтов потомков, и эти списки могут появляться в любом из них. В большинстве случаев будет только несколько элементов, но некоторые из них будут иметь несколько тысяч. Я ожидаю, что результат составит 10-20 тыс. Результатов.

Эта утилита будет запущена на удаленном сервере, и внутренне мы предпочли бы использовать CSOM для отдыха. Я знаком с разработкой веб-части SP, но это первый раз, когда мне нужно было использовать CSOM.

Ферма - это SP 2010 On Prem с 3 WFE, обновленная последним CU.

Непосредственные вопросы:

  • Я бросать "Не удается выполнить это действие." при вызове context.ExecuteQuery(), и я не уверен, почему.
  • Я знаю, что я, вероятно, переназначаю context.ExecuteQuery() и хотел бы знать лучший способ загрузить все эти списки.
  • Мой текущий код получает только мгновенные дочерние сети, когда мне нужны все потомки корня.

Код:

Моя текущая попытка выглядит следующим образом:

using (var ctxt = new ClientContext(url)) 
     { 
      var webs = ctxt.Web.Webs; 
      ctxt.Load(webs); 
      ctxt.ExecuteQuery(); 
      var allItems = new List<ListItem>(); 
      foreach (var web in webs) 
      { 
       ctxt.Load(web.Lists); 
       ctxt.ExecuteQuery(); 
       foreach (var list in web.Lists) 
       { 
        if (list.BaseTemplate == 10003) 
        { 
         ctxt.Load(list); 
         ctxt.ExecuteQuery(); 
         var items = list.GetItems(query); 
         ctxt.Load(items); 
         ctxt.ExecuteQuery(); // <- **throws "Cannot complete this action." on first iteration of loop.** 
         allItems.AddRange(items); 
        } 
       } 
      }     
      results = allItems.Select(ConvertToNeededResultType).ToList(); 
     } 

Запросы выглядят следующим образом:

<View Scope='RecursiveAll'> 
<Webs Scope='SiteCollection' /> <!--**If I omit this line, I get a CollectionNotInitialized exception on allitems.AddRange(items)**--/> 
<Lists ServerTemplate='10003' /> 
<Query> 
    <OrderBy> 
     <FieldRef Name='CreatedOn' Ascending='False' /> 
    </OrderBy> 
    <Where> 
     <And> 
      <Eq> 
       <FieldRef Name='FSObjType' /> 
       <Value Type='Integer'>0</Value> 
      </Eq> 
      <Geq> 
       <FieldRef Name='CreatedOn'/> 
       <Value Type='DateTime' IncludeTimeValue='FALSE'>{0}</Value> 
      </Geq> 
     </And> 
    </Where> 
<Query> 
<ViewFields> 
    <FieldRef Name='Title' Nullable='TRUE' /> 
    <FieldRef Name='URL' Nullable='TRUE' /> 
    <FieldRef Name='CreatedOn' Nullable='TRUE' /> 
    <FieldRef Name='Category' Nullable='TRUE' /> 
    <FieldRef Name='Attachments' Nullable='TRUE' /> 
    <FieldRef Name='ID' /> 
    <ProjectProperty Name='Title' /> 
    <ListProperty Name='Title' /> 
</ViewFields> 
</View> 

где {0} содержит дату, которая количество дней, в которые я хочу вернуться со списком в формате: «yyyy-MM-ddTHH: mm: ssZ»

Я ищу:

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

ответ

0

Я никогда не выяснить «Не удается выполнить это действие» немного, но я решил с требованиями по-другому: мне нужно было два метода, рекурсивные для обхода полотнами и извлечения элементов:

public static IEnumerable<WebLocation> GetWebLocations(string rootWebUrl) 
{ 
    List<WebLocation> results; 
    using (var cntxt = new ClientContext(rootWebUrl)) 
    { 
     var web = cntxt.Web; 
     cntxt.Load(web, w => w.Webs, w => w.Id, w => w.ServerRelativeUrl, w => w.Lists); 
     cntxt.ExecuteQuery(); 
     results = GetWebLocations(cntxt, web, Guid.Empty); 
    } 
    return results; 
} 

private static List<WebLocation> GetWebLocations(ClientContext cntxt, Web currentWeb, Guid parentId) 
{ 
    var results = new List<WebLocation>(); 
    var currentId = currentWeb.Id; 
    var url = currentWeb.ServerRelativeUrl; 
    var location = new WebLocation { ParentSiteID = parentId, SiteID = currentId, WebUrl = url, HotLinksItems = new List<HotLinksItem>() }; 
    foreach (var list in currentWeb.Lists) 
    { 
     cntxt.Load(list, l => l.BaseTemplate, l => l.RootFolder.ServerRelativeUrl); 
     cntxt.ExecuteQuery(); 
     if (list.BaseTemplate == 10003) 
     { 
      var itemCollection = 
         list.GetItems(new CamlQuery 
         { 
          ViewXml = "<View Scope='RecursiveAll'><ViewFields><FieldRef Name='Title' Nullable='TRUE' /><FieldRef Name='ID' /><ProjectProperty Name='Title' /><ListProperty Name='Title' /></ViewFields></View>" 
         }); 
      cntxt.Load(itemCollection); 
      cntxt.ExecuteQuery(); 
      foreach (var item in itemCollection) 
      { 
       var hotlink = new HotLinksItem 
       { 
        Title = item["Title"] != null ? item["Title"].ToString() : null, 
        ID = item["ID"] != null ? item["ID"].ToString() : null, 
       }; 
       location.HotLinksItems.Add(hotlink); 
      } 
     } 
    } 

}

По-прежнему кажется, что я делаю слишком много звонков, но обрезка их с помощью подборов помогла добиться высокой производительности. В целом, против моей фермы эта вещь работает чуть более 30 секунд. (Перед тем как обрезать возвращаемые предметы, он пробежал примерно через 3 минуты.)

Смежные вопросы