7

What is the optimal way to get a list items and their properties from a SP list using Client object model?

Here is the code I'm using.

        string server = "http://localhost";
        ClientContext context = new ClientContext(server);
        Web web = context.Web;
        var spList = web.Lists.GetByTitle("Contact");
        CamlQuery query = new CamlQuery();
        var items = spList.GetItems(query);
        context.Load(items, 
            itema => itema.Include(
                item => item,
                item => item["CustomerId"]));
        context.ExecuteQuery();

        Console.WriteLine("Items");
        foreach (var item in items.ToList())
        {                              
               context.Load(item);
        }

        context.ExecuteQuery();
        foreach (var item in items)
        {
             foreach (var a in item.FieldValues)
             {
                 Console.WriteLine(a.Key + ":" + a.Value.ToString());
             }
         }

I want to remove the single liner foreach used to load list item in the context and if possible load the item field values in the first Execute Query itself.

I tried using the following

 context.Load(items, 
            itema => itema.Include(
                item => item,
                item=> item.FieldValues,
                item => item["CustomerId"]));

which doesn't work.

Any one can provide a cleaner solution?

Sandeep Singh Rawat
  • 1,637
  • 1
  • 14
  • 27

4 Answers4

5

The most efficient way to query SharePoint is to use a CAML Query. By calling (SP)List.GetItems(camlQuery). You will receive always an instance of (SP)ListItemCollection.

So the the most efficient query will look like this

string server = "http://localhost";
var ctx = new ClientContext(server);
var web = ctx.Web;
var list = web.Lists.GetByTitle("Contacts");
var listItemCollection = list.GetItems(CamlQuery.CreateAllItemsQuery());

// always use QueryTrimming to minimize size of 
// data that has to be transfered

ctx.Load(listItemCollection,
           eachItem => eachItem.Include(
            item => item,
            item => item["CustomerId"]));
// ExecuteQuery will pull all data from SharePoint
// which has been staged to Load()
ctx.ExecuteQuery();

foreach(ListItem listItem in listItemCollection)
{
   Console.WriteLine(listItem["CustomerId"]);
}

Thorsten

Thorsten Hans
  • 2,675
  • 19
  • 21
0

I am not 100% sure what properties you would like to get from the fields but you could play around with the following:

SPSite oSite = new SPSite("http://localhost");
SPWeb oWeb = oSite.OpenWeb();

SPList oList = oWeb.Lists["LIST NAME"];
SPFieldCollection oFields = oList.Fields;

foreach (SPField oField in oFields)
{
    Console.WriteLine("Property: " + oField.GetProperty("PROPERTY"));
}

OR

The property you are looking for may actually be under the SPField object. Take a look here for the properties and methods available: http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spfield_members(v=office.12).aspx

Hope this helps. If not some more info on what actual properties you want to get out of the lists' fields might help provide a more accurate solution?

Luke
  • 422
  • 5
  • 15
  • when using client side object model we need to explicitly ask for the properties we are looking for. In this particular case I need the FieldValues collection of the ListItem which is not populated unless I do context.Load on every single list item. – Sandeep Singh Rawat Jan 14 '11 at 00:09
  • your answer is about server object model not client object model which is what the question is asking about. – airmanx86 Jan 21 '11 at 05:39
  • @airmanx86 - yes, good point... sorry i completely misread this one! – Luke Jan 22 '11 at 17:32
0

Change your code to this.

IQueryable<ListItem> items = spList.GetItems(query);

Then call LoadQuery() instead of Load()

context.LoadQuery(items);

You may add additional expressions to read the property of the ListItem you wanted like this:

context.LoadQuery(items.Include(item => item["CustomerId"]));

I am actually having problem trying to do item => item.FieldValues, but item => item.FieldValuesAsText works. I am not sure why :( But just doing context.LoadQuery(items) should do what you want.

airmanx86
  • 992
  • 1
  • 8
  • 16
0
CamlQuery camlQuery = new CamlQuery();
camlQuery.ViewXml = "<View Scope=\"RecursiveAll\"><Query><Where><Eq><FieldRef Name=\"FSObjType\" /><Value Type=\"Integer\">0</Value></Eq></Where></Query><RowLimit>100</RowLimit></View>";
ListItemCollection listItemCollection = srcList.GetItems(camlQuery);
srcContext.Load(listItemCollection);
await srcContext.ExecuteQueryAsync();

Querying for FSObjType=0 returns the items with all fields populated! See: https://blog.velingeorgiev.com/sharepoint-online-csom-all-list-items-content-caml-query

The query gets all list items in batches of 100. May you just could add an AND clause to the query to get specific items.

AlyaKoni
  • 1
  • 1