Thursday, May 8, 2008

Sharepoint Item Update is a NIGHTMARE!

What a strange statement!

Why?

Actually, using item updates is easy and you get what you want, your item updated. Right.
Let's try an example:
You have to create several items, in several content types, in several folders. Let's assume you want to have a kind of hierarchy like:

  • Folder 1 with a specific content type
    • Items with a specific content type inside this folder
    • A new folder structure with a specific content type
      • Items inside this folder

Logically, you use a code like the following for the folder:

SPFolder ArchiveFolder = MonthFolder.SubFolders.Add("Folder 1");
ArchiveFolder.UniqueContentTypeOrder = contentTypes;
ArchiveFolder.Update();

//Process all about the folder item
ArchiveFolder.Item["Title"] = this._PONumber;
ArchiveFolder.Item["PONumber"] = this._PONumber;
ArchiveFolder.Item["ContentTypeId"] = ePOFolder.Id.ToString(); // Fix the content type for the folder
ArchiveFolder.Item.Update();

And the following code for a document:

SPFile fileH = HistoryFolder.Files.Add(this.getUniqueFileName(), this._docSize);
fileH.Update();
//Getthe item and fill it with history data, plus the content type id
SPListItem itemH = fileH.Item;
itemH["Title"] = "TITRE";
itemH["ContentTypeId"] = historyCT.Id.ToString();
itemH.UpdateOverwriteVersion();

But all of this works fine if you have only a small number of items, ie less than let's say 50000 records in your list (not only in your container)

If you are above this number of records, things start to be less fancy. One update takes 1 second, then 2 seconds, then 4 seconds, etc... I had the case with more than 120 000 records, and one update could take 1 or 2 minutes! Unbelievable.

After googling and looking at my own experience (see here) I've solved one aspect, uploading documents with meta-data :

First, store your item data into a Hashtable:

Hashtable result = new Hashtable();
result.Add("Title",_PONumber); 
result.Add("HistoryDescription",_historyDescription);
result.Add("HistoryOutcome",_historyOutcome);
result.Add("ContentTypeId", CT_Id);

then use the corresponding overload of SPFiles.Add():

SPFile fileH = HistoryFolder.Files.Add(this.getUniqueFileName(), this._docSize, result);

And that's all! You don't need any update! It's automatically done! Great. It was not so obvious but there is an overload for this method.

Now, what about folders. If you try SPFolders.Add()... you don't see any overload like with SPFiles. So you may think there is no way to use the same technic in order to avoid at least one Update (on item)?

Well, have a look on the bad (un)documented property "Properties" of SPFolder: it is a Hashtable! So you can use the add method to add your items properties, then you only need one update, instead of two. Here is the previous code modifed:

ArchiveFolder = MonthFolder.SubFolders.Add("Folder 1");
ArchiveFolder.UniqueContentTypeOrder = contentTypes;
//Process all about the folder item
ArchiveFolder.Properties.Add("Title", this._PONumber);
ArchiveFolder.Properties.Add("PONumber", this._PONumber);
ArchiveFolder.Properties.Add("ContentTypeId", ePOFolder.Id.ToString()); // Fix the content type for the folder
ArchiveFolder.Update();

Be aware of one thing: in Properties you can only add basic data type, like DateTime, String, Int... but no Double for instance. So be careful if you numeric data.

Summary:

We have now only one update for each folder and no more updates for documents. With my set of 120 000 rows, actually more than 500 000, it takes less than one second to add 2 folders and 12 documents. In one minute now I can process 70 times more documents and folders than before!

1 comment:

Unknown said...

How do I set the "creted by" and "modified by"properties? thx.