1

Let's say I have two lists with following fields:

List A
------
+ Title
+ MultiLookupOnListB (Lookup List: List B; Lookup Field: Title)

List B
------
+ Title
+ LookupOnListA (Lookup List: List A; Lookup Field: Title)

So basically a List A Item can reference one or more List B Items while a List B Item can only reference one List A Item. I already set List B -> List A lookup with CSR, but the List A -> List B lookup needs to be done in an event receiver since I need access to resources that aren't available when using JS.

So I use ItemUpdating for adding List B items to List A multi lookup field. Only problem is, when two list items are created at the same time, the code is too fast (^^) and the second event basically overwrites the first event so I end up with only one referenced List B Item.

/// <summary>
/// An item was updated.
/// </summary>
public override void ItemUpdated(SPItemEventProperties properties)
{
    base.ItemUpdated(properties);
    var listItem = properties.ListItem;
    var listAItem = GetListAItemFromSomewhere();

    SPFieldLookupValueCollection listItemALookup = listAItem["MultiLookupOnListB "] as SPFieldLookupValueCollection;
    if (listItemALookup.OfType<SPFieldLookupValue>().Where(pdr => pdr.LookupId == listItem.ID).Count() < 1)
    {
        listItemALookup.Add(new SPFieldLookupValue(listItem.ID, listItem.Title));

        listAItem["MultiLookupOnListB "] = listItemALookup;
        listAItem.SystemUpdate(false);
    }
}

I have already tried to set the ItemUpdating event to synchronous, but that didn't work. So, any ideas on how to best do this?

1

Setting the event as synchronous cannot help indeed, since it means "blocking" with regards to the current request; it's not about blocking all requests in the execution pipe.
Your option here would be to use a real semaphore/locking system. That could be simple if you're in a single-server farm, as opposed to multi-server farm. What's your situation regarding your farm setup (I mean essentially: how many WFE servers)?

EDIT: farm-wide lock:

It's not simple to acquire a lock visible from all machines in the farm. One approach is to store the lock state in the SQL database.

https://stackoverflow.com/a/18738491 explains how to implement it in C#.
It will probably require some changes to adapt it to a SharePoint context: e.g. reverting to the process (app pool) identity before making the SQL calls, so you have the correct permissions (this can be done by issuing the commands from inside a using (HostingEnvironment.Impersonate()) section).

  • our client has multiple servers, some for external and some for internal sites. but it really should support both scenarios. if possible, this should also be done with minimal effort. how would you achieve this lock in sharepoint if I might ask? – LeonidasFett May 31 '17 at 18:41
  • I have solved my problem from a completely different angle so I basically discarded the whole ItemUpdating attempt. In fact, I am going to probably remove the multi lookup field altogether and just use CAML to get my results which is possible because of the LookupOnListA field. Thank you though for your effort, it's still appreciated. :-) – LeonidasFett Jun 2 '17 at 16:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.