Search code examples
c#linqdatatablecsom

More efficient way of using LINQ to compare two items?


I am updating records on a SharePoint list based on data from a SQL database. Lets say my table looks something like this:

VendorNumber ItemNumber Descrpition
1001 1 abc
1001 2 def
1002 1 ghi
1002 3 jkl

There can be multiple keys in each table. I am trying to make a generic solution that will work for multiple different table structures. In the above example, VendorNumber and ItemNumber would be considered keys.

I am able to retrieve the SharePoint lists as c# List<Microsoft.SharePoint.Client.ListItem>

I need to search through the List to determine which individual ListItem corresponds to the current SQL datarow I am on. Since both ListItem and DataRow allow bracket notation to specify column names, this is pretty easy to do using LINQ if you only have one key column. What I need is a way to do this if I have anywhere from 1 key to N keys. I have found this solution but realize it is very inefficient. Is there a more efficient way of doing this?

List<string> keyFieldNames = new List<string>() { "VendorNumber", "ItemNumber" };
List<ListItem> itemList = MyFunction_GetSharePointItemList();
DataRow row = MyFunction_GetOneRow();

//this is the part I would like to make more efficient:
foreach (string key in keyFieldNames)
{
     //this filters the list with each successive pass.
     itemList = itemList.FindAll(item => item[key].ToString().Trim() == row[key].ToString().Trim());
}

Edited to Add: Here is a link to the ListItem class documentation: Microsoft.SharePoint.Client.ListItem

While ListItem is not a DataTable object, its structure is very similar. I have intentionally designed it so that both the ListItem and my DataRow object will have the same number of columns and the same column names. This was done to make comparing them easier.


Solution

  • After I stopped looking for an answer, I stumbled across one. I have now realized that using a .Where is implemented using deferred execution. This means that even though the foreach loop iterates several times, the LINQ query executes all at once. This was the part I was struggling to wrap my head around.

    My new sudo code:

    List<string> keyFieldNames = new List<string>() { "VendorNumber", "ItemNumber" };
    List<ListItem> itemList = MyFunction_GetSharePointItemList();
    DataRow row = MyFunction_GetOneRow();
    
    //this is the part I would like to make more efficient:
    foreach (string key in keyFieldNames)
    {
         //this filters the list with each successive pass.
         itemList = itemList.Where(item => item[key].ToString().Trim() == row[key].ToString().Trim());
    }
    

    I know that the .ToString().Trim() is still inefficient, I will address this at some point. But for now at least my mind can rest knowing that the LINQ executes all at once.