mandag den 25. november 2013

Ensuring a child item exists

Sometimes, we need to get an item if it exists, and if it doesn't, create it instead.

This normally happens when we have something that needs to be placed inside folders, to ensure there aren't too many items in the same folder.

Lets say, that we have a task, that imports employees from an external system, and for each of these create an item - this can quickly result in problems if there are more than a few hundred items.

The normal way to solve this, is to divide the users into folders based on the first character in their name (or what else is used to differentiate them).

If we take the employee "A1D2", we would create a structure like this, for the item: "Employees/A/1/A1D2" .

Here comes the problem - to create the item, we need to make sure the folder "1" exists, but to ensure that, we need to ensure that the folder "A" exists, and so forth..

To do this, we have created a helper function, that returns a child item if it exists, and if it doesn't, we create the item, and return the new item - here is the code for the function:

public static Item EnsureChildItem(Item parentItem, string childName, TemplateID templateID, Action<Item> createdAction)
{
    if (parentItem == null)
    {
        throw new ArgumentNullException("parentItem", "parentItem must not be null");
    }

    if (string.IsNullOrEmpty(childName))
    {
        throw new ArgumentException("childName must not be empty", "childName");
    }

    string itemNameError = ItemUtil.GetItemNameError(childName);

    if (!string.IsNullOrEmpty(itemNameError))
    {
        throw new ArgumentException("childName is invalid - message: " + itemNameError, "childName");
    }

    Item childItem = parentItem.Children[childName];

    if (childItem != null)
    {
        return childItem;
    }

    childItem = parentItem.Add(childName, templateID);

    if (createdAction != null)
    {
        createdAction(childItem);
    }

    return childItem;
}

First we check if the parameters is valid, and if they are, we check if the item exist - if it does, we just return it.

If it doesn't we create it, and run the passed Action if it is defined - this allows the called to pass a function to be called if the item was created.
This is pretty clever, if I should say so, since it allows you to do anything to the new item, such as publish it (which is what we would normally do), so you're always sure the item is published.

It's a pretty small function, but it really makes it easy, to be able to do this:

string employeeName = GetEmployeeName();
Item employeeFolder = GetEmployeeFolder();

// Get the first level folder.
employeeFolder = HelperFunctions.EnsureChildItem(employeeFolder, employeeName[0].ToString(), new TemplateID(TEMPLATE_ID), item => HandleNewItem(item));

// Get the second level folder.
employeeFolder = HelperFunctions.EnsureChildItem(employeeFolder, employeeName[1].ToString(), new TemplateID(TEMPLATE_ID), item => HandleNewItem(item));

This way, we know that employeeFolder is containing the folder where the new employee item is to be created, and we know for sure, that it exists.

Nice :-)

Ingen kommentarer:

Send en kommentar