How to query large sharepoint list - sharepoint

I have a list that contains tens of thousands of items.
I have tried to limit the query using a where clause, like this:
var list = Context.Web.Lists.GetByTitle(title);
string query = $#"<Query>
<Where>
<Lt>
<FieldRef Name='ID' /><Value Type='Integer'>100</Value>
</Lt>
</Where>
<OrderBy><FieldRef Name='ID' Ascending='true' /></OrderBy>
</Query>";
var camlQuery = new CamlQuery();
camlQuery.ViewXml = query;
var items = list.GetItems(camlQuery);
Context.Load(items);
Context.ExecuteQuery();
But I'm getting SPQueryThrottledException anyway:
The attempted operation is prohibited because it exceeds the list
view threshold enforced by the administrator.
How do I query large sp list?

You need to modify your CAML query and use pagination using ListItemCollectionPosition as well as set the RowLimit value.
Try and modify the below sample code:
var list = Context.Web.Lists.GetByTitle(title);
ListItemCollectionPosition position = null;
try
{
do
{
string query = $#"<View>
<ViewFields>
<FieldRef Name='Title'/>
</ViewFields>
<Query>
<Where>
<Lt>
<FieldRef Name='ID' /><Value Type='Integer'>100</Value>
</Lt>
</Where>
<OrderBy><FieldRef Name='ID' /></OrderBy>
</Query><RowLimit>100</RowLimit></View>";
var camlQuery = new CamlQuery();
camlQuery.ViewXml = query;
var items = list.GetItems(camlQuery);
Context.Load(items);
Context.ExecuteQuery();
position = items.ListItemCollectionPosition;
foreach (ListItem listItem in items)
Console.WriteLine("Title: {0}", listItem["Title"]);
}
while (position != null);
}
catch(Exception ex)
{
}
Updated CAML query as per comments:
string query = $#"<View>
<Query>
<Where>
<And>
<Geq>
<FieldRef Name='ID' /><Value Type='Integer'>1</Value>
</Geq>
<Leq>
<FieldRef Name='ID' /><Value Type='Integer'>1000</Value>
</Leq>
</And>
</Where>
<OrderBy><FieldRef Name='Created' /></OrderBy>
</Query><RowLimit>100</RowLimit></View>";

Related

How do I connect to sharepoint syntex library in c# and read files from there?

private static void sharepointConnection()
{
try
{
Console.WriteLine("Trying to connect");
const string rootUrl = "";
const string reqUrl = "";
const string pwd = "";
const string username = "";
SecureString securestring = new SecureString();
pwd.ToCharArray().ToList().ForEach(s => securestring.AppendChar(s));
ClientContext context = new ClientContext(reqUrl);
context.Credentials = new SharePointOnlineCredentials(username, securestring);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Use CSOM code in below format after authentication:
public static List<ListItem> GetAllDocumentsInaLibrary()
{
List<ListItem> items = new List<ListItem>();
string sitrUrl = "https://spotenant.sharepoint.com/sites/yoursite";
using (var ctx = new ClientContext(sitrUrl))
{
//ctx.Credentials = Your Credentials
ctx.Load(ctx.Web, a => a.Lists);
ctx.ExecuteQuery();
List list = ctx.Web.Lists.GetByTitle("Documents");
ListItemCollectionPosition position = null;
// Page Size: 100
int rowLimit = 100;
var camlQuery = new CamlQuery();
camlQuery.ViewXml = #"<View Scope='RecursiveAll'>
<Query>
<OrderBy Override='TRUE'><FieldRef Name='ID'/></OrderBy>
</Query>
<ViewFields>
<FieldRef Name='Title'/><FieldRef Name='Modified' /><FieldRef Name='Editor' />
</ViewFields>
<RowLimit Paged='TRUE'>" + rowLimit + "</RowLimit></View>";
do
{
ListItemCollection listItems = null;
camlQuery.ListItemCollectionPosition = position;
listItems = list.GetItems(camlQuery);
ctx.Load(listItems);
ctx.ExecuteQuery();
position = listItems.ListItemCollectionPosition;
items.AddRange(listItems.ToList());
}
while (position != null);
}
return items;
}
References:
Get all files from a SharePoint Document Library using CSOM
Download all files from Sharepoint Online Document Library using C# CSOM

How to get files>5000 in share point

I have a sharepoint location where the total number of files are more than 5000. In this case I am not able to view them in file explorer. Is there any other option to retrieve the files available in sharepoint programatically and not using sharepoint website
You can index the column and use below code :
$list = $ctx.Web.Lists.GetByTitle($DocLibName)
$ctx.Load($list)
$ctx.ExecuteQuery()
## View XML
$qCommand = #"
<View Scope="RecursiveAll">
<Query>
<OrderBy><FieldRef Name='ID' Ascending='TRUE'/></OrderBy>
</Query>
<RowLimit Paged="TRUE">5000</RowLimit>
</View>
"#
## Page Position
$position = $null
## All Items
$allItems = #()
Do{
$camlQuery = New-Object Microsoft.SharePoint.Client.CamlQuery
$camlQuery.ListItemCollectionPosition = $position
$camlQuery.ViewXml = $qCommand
## Executing the query
$currentCollection = $list.GetItems($camlQuery)
$ctx.Load($currentCollection)
$ctx.ExecuteQuery()
## Getting the position of the previous page
$position = $currentCollection.ListItemCollectionPosition
# Adding current collection to the allItems collection
$allItems += $currentCollection
}
# the position of the last page will be Null
Until($position -eq $null)
This code is resembling the pagination behaviour.
$position will the previous page index.
Hope this helps.
You could refer to the code in this post:
https://sharepoint.stackexchange.com/questions/128373/large-list-issue-with-csom
Note: you have to use indexed column in the camel query.
ClientContext clientContext = new ClientContext("weburl");
List list = clientContext.Web.Lists.GetByTitle("ListTitle");
ListItemCollectionPosition position = null;
do
{
CamlQuery camlQuery = new CamlQuery();
camlQuery.ListItemCollectionPosition = position;
camlQuery.ViewXml = #"<View>
<ViewFields>
<FieldRef Name='Title'/>
</ViewFields>
<RowLimit>5000</RowLimit>
</View>";
ListItemCollection listItems = list.GetItems(camlQuery);
clientContext.Load(listItems);
clientContext.ExecuteQuery();
position = listItems.ListItemCollectionPosition;
foreach (ListItem listItem in listItems)
Console.WriteLine("Title: {0}", listItem["Title"]);
}
while(position != null)

Check if Calendar (List) is free in SharePoint CSOM

I am writing javascript (CSOM) code in SharePoint to add items to SharePoint Calendar app (list).
I want to add these records only if calendar is free during the specified time.
i.e in below ex, I want to check if calendar is free from 08:00 to 08:15 before adding
var itemCreateInfo = new SP.ListItemCreationInformation();
var listItem = list.addItem(itemCreateInfo);
var startdate = new Date('2017-10-21 08:00 GMT+0000').toISOString();
var enddate = new Date('2017-10-21 08:15 GMT+0000').toISOString();
listItem.set_item("Title", "My Event");
listItem.set_item("EventDate", startdate);
listItem.set_item("EndDate", enddate);
listItem.set_item("Location", "MyCalander");
listItem.update();
Here is a query you can use: (The caml value looks terrible so I'll post the xml below)
function queryCalendar(startDate, endDate) {
var context = SP.ClientContext.get_current();
var list = context.get_web().get_lists().getByTitle("Calendar");
var caml = "\n<View>\n <Query>\n <Where>\n <And>\n <Lt>\n <FieldRef Name='EventDate' />\n <Value Type='DateTime' IncludeTimeValue='True' StorageTZ='TRUE'>" + endDate.toISOString() + "</Value>\n </Lt>\n <Gt>\n <FieldRef Name='EndDate' />\n <Value Type='DateTime' IncludeTimeValue='True' StorageTZ='TRUE'>" + startDate.toISOString() + "</Value>\n </Gt>\n </And>\n </Where>\n </Query>\n <ViewFields>\n <FieldRef Name='EventDate' />\n <FieldRef Name='EndDate' />\n <FieldRef Name='Title' />\n </ViewFields>\n</View>\n\n";
var query = new SP.CamlQuery();
query.set_viewXml(caml);
var listItems = list.getItems(query);
context.load(listItems);
context.executeQueryAsync(function (sender, args) {
if (listItems.get_count() > 0) {
console.warn("That time is already booked");
}
else {
console.log("that time is good");
}
}, function (sender, args) {
console.error(args.get_message());
});
}
Here is how I am calling it:
SP.SOD.executeOrDelayUntilScriptLoaded(function () {
queryCalendar(new Date(2019, 4, 27, 8), new Date(2019, 4, 27, 9));
}, "SP.js");
I use the following XML for the CAML:
<View>
<Query>
<Where>
<And>
<Lt>
<FieldRef Name='EventDate' />
<Value Type='DateTime' IncludeTimeValue="True" StorageTZ='TRUE'>enddate</Value>
</Lt>
<Gt>
<FieldRef Name='EndDate' />
<Value Type='DateTime' IncludeTimeValue="True" StorageTZ='TRUE'>starttime</Value>
</Gt>
</And>
</Where>
</Query>
<ViewFields>
<FieldRef Name='EventDate' />
<FieldRef Name='EndDate' />
<FieldRef Name='Title' />
</ViewFields>
</View>
Make sure to replace "enddate" and "startdate" with a proper date value and use date.toISOString() method (which might not work in IE).

Error with sharepoint client object model

I got the following error while running SharePoint ClientObject Model. I went through my code and checked if I missed any thing to load, but didn't see.
"Process is Terminated: The property or field has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested."
I am not sure what I am missing after searching about this for a couple of hour.
The following is my code. Hope any one can help.
public static void UpdatePackageStatus(string Teamsite, string Libname, string Packagename, string User, string Password, string Domain, string PackageStatus, string DeploymentSucceeded, string query)
{
using(clientOM.ClientContext Ctx = new clientOM.ClientContext(Teamsite))
{
Ctx.Credentials = new System.Net.NetworkCredential(User, Password, Domain);
clientOM.Web Web = Ctx.Web;
Ctx.Load(Web);
Ctx.ExecuteQuery();
clientOM.List list = Web.Lists.GetByTitle(Libname);
Ctx.Load(list);
Ctx.ExecuteQuery();
clientOM.CamlQuery CamlQuery = new clientOM.CamlQuery();
CamlQuery.ViewXml = query;
clientOM.ListItemCollection Items = list.GetItems(CamlQuery);
Ctx.Load(Items);
Ctx.ExecuteQuery();
if(Items.Count > 0)
{
clientOM.ListItem Item = Items.GetById(Items[0].Id);;
Ctx.Load(Item);
Ctx.ExecuteQuery();
if(Item.DisplayName == Packagename)
{
Item[PackageStatus] = DeploymentSucceeded;
Item.Update();
Ctx.ExecuteQuery();
}
}
}
}
All used fields like DisplayName, Id and PackageStatus should be specified manually. You can use CAML query and write something like this:
string queryText = #"<View>
<Query>
<Where>
<Eq>
<FieldRef Name='{0}'/>
<Value Type='Text'>{1}</Value>
</Eq>
</Where>
</Query>
</View>";
CamlQuery query = new CamlQuery();
query.ViewXml = string.Format(queryText, 'DisplayName', Packagename); //FieldRef = internal field name
ListItemCollection listItems = list.GetItems(query);
Ctx.Load(listItems, items => items.Include(item => item[PackageStatus]);
Ctx.ExecuteQuery();
if (listItems.Count > 0)
{
listItems[0][PackageStatus] = DeploymentSucceeded;
Item.Update();
Ctx.ExecuteQuery();
}
I see a fix.
Instead of using Item.DisplayName, I can use File object. It works when I use File and instantiating it by load(File) like other property.
clientOM.File file = Item.File;
Ctx.Load(file);
Ctx.ExecuteQuery();
if(file.Name == Packagename)
{
Item[PackageStatus] = DeploymentSucceeded;
Item.Update();
Ctx.ExecuteQuery();
}

Get the URL of a List in sharepoint using Caml Query

I am using SPSiteDataQuery to display documents from different lists. I display the documents using a Gridview. One of the columns of the Gridview is an hyperlinkfield. How can I set the url of each document since each of them comes from different different document libraries? For your information, I am using Caml Query to filter the documents.
Please help me.
here is the code:
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using System.Data;
using Microsoft.SharePoint.Utilities;
namespace Uniway.FOD.Intranet.ControlTemplates
{
public partial class Documents : UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
GridView1.DataSource = GetAllDocuments();
// Set up the field bindings.
BoundField boundField = new BoundField();
boundField.HeaderText = "File name";
boundField.DataField = "Title";//"LinkFilename";
GridView1.Columns.Add(boundField);
HyperLinkField hyperlinkField = new HyperLinkField();
hyperlinkField.HeaderText = "Link name";
hyperlinkField.DataTextField = "LinkFileName";
hyperlinkField.DataNavigateUrlFields = new[] { "LinkFileName" };
hyperlinkField.DataNavigateUrlFormatString = "{0}";
GridView1.Columns.Add(hyperlinkField);
BoundField boundField2 = new BoundField();
boundField2.HeaderText = "Link File Name";
boundField2.DataField = "LinkFilename";
GridView1.Columns.Add(boundField2);
GridView1.DataBind();
}
public DataTable GetAllDocuments()
{
SPSiteDataQuery objSPSiteDataQuery = null;
SPWeb objSPWeb = null;
DataTable objDataTable = null;
objSPWeb = SPContext.Current.Web;
objSPSiteDataQuery = new SPSiteDataQuery();
//Specify the fields to be fetched in the results.Similar to select clause of an SQL query
objSPSiteDataQuery.ViewFields = "<FieldRef Name=\"LinkFilename\"/>" +
"<FieldRef Name=\"Title\" />" +
"<FieldRef Name=\"Created\" />" +
"<FieldRef Name=\"Modified\"/>" +
"<FieldRef Name=\"Editor\"/>";
//specifying list server template=101 so that it will query only document libraries
objSPSiteDataQuery.Lists = "<Lists ServerTemplate=\"101\" BaseType=\"1\" Hidden=\"FALSE\" MaxListsLimit=\"0\"/>";
objSPSiteDataQuery.RowLimit = 1000;
objSPSiteDataQuery.Webs = "<Webs Scope=\"Recursive\"/>";
//querying all documents of the content type 'CT23December1' having version=1.0
objSPSiteDataQuery.Query = #"<Where>
<Eq>
<FieldRef Name='File_x0020_Type' />
<Value Type='Text'>doc</Value>
</Eq>
</Where><OrderBy><FieldRef Name='Modified' Ascending='False' /></OrderBy>";
objDataTable = objSPWeb.GetSiteData(objSPSiteDataQuery);
return objDataTable;
}
}
}
You can use some internal fields to build a link to the document. Here are some useful ones with an example of the data in each field:
FileRef - 1;#sites/SiteCollection/Kit/Kits Site Documents/Excel Report.xls
FileLeafRef - 1;#Excel Report.xls
FileDirRef - 1;#sites/SiteCollection/Kit/Kits Site Documents
ServerUrl - /sites/SiteCollection/Kit/Kits Site Documents/Excel Report.xls
EncodedAbsUrl - http://server/sites/SiteCollection/Kit/Kits%20Site%20Documents/Excel%20Report.xls
You'll just add one of the fields above as another viewfield to objSPSiteDataQuery.ViewFields:
objSPSiteDataQuery.ViewFields = "<FieldRef Name=\"ServerUrl\"/>" +
"<FieldRef Name=\"LinkFilename\"/>" +
"<FieldRef Name=\"Title\" />" +
"<FieldRef Name=\"Created\" />" +
"<FieldRef Name=\"Modified\"/>" +
"<FieldRef Name=\"Editor\"/>";
I did it like this:
row["AbsolutePath"] = String.Format("{0}{1}", row["EncodedAbsUrl"], row["FileRef"].ToString().Substring(row["FileRef"].ToString().IndexOf("#") + 1));

Resources