Archive SharePoint List Items To SQL Database using CSOM - Part Two

Before reading this article, please go through the following article series:

In the Part One of this article we generated table script. Now we can execute this script to create the SQL Table based on list schema.

2 of 3 key tasks are completed.

  1. Create a List view which will have the items to be archived.
  2. Create the SQL Table based on the List Schema.

Now the most important and complex part is to perform the Archival Operation. Before moving ahead make sure your Table is created in the database.

We are going to perform the following actions:

  1. Generate the Insert Query.
  2. Dynamically populate the Insert Query with the List Item column values.
  3. Loop on the View Data and archive all the items into the Table and Delete It from SharePoint List.

Below code snippet generates the Insert Query:

  1. public StringBuilder GenerateInsertQuery(List list, string viewName)  
  2. {  
  3.     StringBuilder sbInsertParm = newStringBuilder();  
  4.     var listFieldCollection = list.Fields;  
  5.     list.Context.Load(listFieldCollection);  
  6.     list.Context.ExecuteQuery();  
  7.     int count = 1;  
  8.     foreach(var field in listFieldCollection)  
  9.     {  
  10.         try  
  11.         {  
  12.             if (FilterColumn(field))  
  13.             {  
  14.                 var fieldtitle = field.Title.Replace(' ''_');  
  15.                 sbInsertParm.AppendFormat("@{0}""p" + count++);  
  16.                 sbInsertParm.Append(",");  
  17.                 sbInsertTable.AppendFormat("[{0}]", fieldtitle);  
  18.                 sbInsertTable.Append(",");  
  19.             }  
  20.   
  21.         } catch (Exception)   
  22.         {  
  23.             throw;  
  24.         }  
  25.     }  
  26.     sbInsertParm.Remove(sbInsertParm.Length - 1, 1);  
  27.     sbInsertTable.Append(",");  
  28. }  
  29. sbInsertTable.Remove(sbInsertTable.Length - 1, 1);  
  30. return sbInsertTable;  
  31. }  
In this code, I am loading all the List Field Collection and Looping into it, same as creating table script so that the columns generated during CreateTableScript method and column in insert query is the same.

Note: FilterColumn method is same as CreateTableScript Method.

Now we generated the insert query, we are going to perform the Archival operation in the below code snippet:
  1. public void ArchiveAndDelete(string insertcmd, List list, string ViewName)  
  2. {  
  3.     _context = list.Context asClientContext;  
  4.     _context.RequestTimeout = System.Threading.Timeout.Infinite;  
  5.     var view = list.Views.GetByTitle(ViewName);  
  6.     _context.Load(view);  
  7.     _context.ExecuteQuery();  
  8.     //If the List has Items more than its threshold value, we have to use ListItemCollectionPosition to get items.  
  9.     ListItemCollectionPosition itemCreateInfo = null;  
  10.     //Get Batch items based on rowlimit   
  11.     string viewquery = "<View><Query>" + view.ViewQuery + "</Query><RowLimit>" + Constants.ROWLIMIT + "</RowLimit></View>";  
  12.     CamlQuery query = newCamlQuery()  
  13.     {  
  14.         ViewXml = viewquery  
  15.     };  
  16.     //Get the View Fields from List  
  17.     var lc = GetListColumns(list);  
  18.     do {  
  19.         query.ListItemCollectionPosition = itemCreateInfo;  
  20.         var items = list.GetItems(query);  
  21.         _context.Load(items);  
  22.         _context.ExecuteQuery();  
  23.         ArchiveItems(items, insertcmd, lc);  
  24.         itemCreateInfo = items.ListItemCollectionPosition;  
  25.   
  26.     } while (itemCreateInfo != null);  
  27.   
  28. }  
In the above code snippet, ArchiveAndDeletemethod take 3 parameters. InsertCmd which we generated, List to be Archived, and the View from where we pull the Filtered data.

ListItemCollectionPosition stores the last index of the items fetched from list. It is useful when you want to apply paging or when you want to fetch items from the list which has crossed its threshold limit.

Value of itemCreateInfo is null when there are no more items left in the specified query.

ArchiveandDelete uses 2 private methods GetListColumns and ArchiveItems method.
  1. private List < string > GetListColumns(List list)  
  2. {  
  3.     try  
  4.     {  
  5.         List < string > viewcolumns = newList < string > ();  
  6.         var listfields = list.Fields;  
  7.         _context.Load(listfields);  
  8.         _context.ExecuteQuery();  
  9.         foreach(var field in listfields)   
  10.         {  
  11.             if (FilterColumn(field))  
  12.                 viewcolumns.Add(field.InternalName);  
  13.         }  
  14.         viewcolumns.AddRange(Constants.DEFAULTFIELDS.Split(','));  
  15.         return viewcolumns;  
  16.     } catch (Exception)   
  17.     {  
  18.         throw;  
  19.     }  
  20. }  
GetListColumns returns the collection of internal field names in a list which is then used to get the items properties against those fields. For example:
  1. item[FieldInternalname]  
  2.   
  3. private void ArchiveItems(ListItemCollection items, string insertcmd, List < string > vc)   
  4. {  
  5.   
  6.     foreach(var item in items.ToList())   
  7.     {  
  8.         int itemid = item.Id;  
  9.         string itemname = string.Empty;  
  10.         itemname = itemname.Replace("'""");  
  11.         try {  
  12.             //Build Insert command  
  13.             var insertVal = GetInsertValue(item: item, viewColumns: vc, itemId: itemid, listName: ListName);  
  14.             var insertCommand = newStringBuilder(insertcmd.Substring(0, insertcmd.IndexOf("VALUES")));  
  15.             insertCommand.Append("VALUES (" + insertVal + ")");  
  16.   
  17.             // send insert command to database.  
  18.             int success = 0;  
  19.             success = InsertData(insertCommand.ToString());  
  20.   
  21.             if (success == 1)  
  22.             {  
  23.                 // item was inserted successfully. log it to tracking db.  
  24.   
  25.                 Console.WriteLine("Item ID: {0} Name: {1} Archived to SQL Table Successfully.", itemid, itemname);  
  26.                 try  
  27.                 {  
  28.                     item.DeleteObject();  
  29.                     items.Context.ExecuteQuery();  
  30.                     // item was deleted from List. log it to tracking DB.  
  31.                     Console.WriteLine("Item ID: {0} Name: {1} Deleted from List", itemid, itemname);  
  32.                 } catch (Exception ex)   
  33.                 {  
  34.                     //Log  
  35.                 }  
  36.             }  
  37.   
  38.         } catch (Exception ex)   
  39.         {  
  40.             //Log   
  41.         }  
  42.     }  
  43. }  
ArchiveItems method loops through the listItemColelction and for each item it builds the insert command by loading the values from the respective fields. And once the insert command is completed we are just adding it to the SQL table using ADO.NET.
 
Read more articles on SharePoint: