Locking (new)

Example of locking

Let’s say we have two users, A (left) and B (right), which load the same item in Artikelstamm. Both of them will see a closed lock:

User A makes an edit on the suchwort. His lock is “opened” and user B gets an instant notification that the record is locked:

User B can attempt to make changes such as edit text fields, press Save, Delete, etc., but will get an error message and the pending edit reverted:

When hovering over the red lock, you can also find out who is currently locking the record:

When user A saves the record, user B gets a notification that his record has just been refreshed with the latest information:

Remark: The lock is maintained after saving, since it could be an intermediate save and the user currently locking the record may want to make further changes to it.

The user currently locking the record can click on the lock menu item to release the lock, thus allowing another user to edit the record:

If the record is not yet locked, the user can explicitly lock the record without performing any edit by clicking on the lock:

When the user currently locking loads another record or closes the module, the lock is automatically released and other users viewing the information will have their lock status updated:

In order to activate this functionality, you need to perform the following actions on the module:

  • Make sure that the main DataSet has locking activated for the main table:

  • Set the “LockOnRetrieve” property to true in the BusinessObject (formerly named “AutoLock”), to make sure the record is automatically blocked on retrieve when the BusinessObject is used programmatically:

protected busArt() : this("dsArt")
{
}

protected busArt(string dataSetId)
{
    dSet = new xDataSet(dataSetId);
    dSet.LockOnRetrieve = true;
    tSet = new dsArt (dset);
}
  • Wrap the BusinessObject retrieve function in a DataRetrieveTransition method call:

Mouse.OverrideCursor = Cursors.Wait;
try
{
    var resourceName = l.Translate("Artikel '{0}' ", artNr);   
    bool retrieveSuccess = DataRetrieveTransition(resourceName, 
        () => BusObj.Retrieve(artNr));
        
    if (!retrieveSuccess)
    {
        Log.Error(l.Translate("Artikel {0} konnte nicht geladen werden.", artNr));
        return;
    }
}
finally
{
    Mouse.OverrideCursor = null;
}
  • Set the “UseInteractiveLocking” property on the WHO for all constructors:

public wndItem() : base("busArt")
{
    UseInteractiveLocking = true;
}

public wndItem(string busObjId) : base(busObjId)
{
    UseInteractiveLocking = true;
}
  • Override OnReload to correctly handle the refresh when the current record is changed by another user:

protected override void OnReload(bool quiet)
{
    base.OnReload(quiet)
    
    var artNr = BusObj.tSet.Args_artnr;
    if (!artNr.IsNullOrEmpty)
    {
        RetrieveArt(artNr, quiet: quiet);
    }
}

Remark: the quiet flag should be used to suppress potential calls to OkToContinue, so that even if the module gets somehow marked as “dirty”, no “Do you want to save” MessageBox will be presented to the user (important since the user could be in a totally different module when the record gets remotely updated)

  • Mark controls that shouldn’t trigger locking by setting the “PreventLock” property to true:

Remark: The framework makes sure that the main TextBoxSearch, as well as “New”, “Back” and “Forward” menu items do not trigger locking of the current record. For the rest of the controls, it’s the responsibility of the module implementer to set the PreventLock property correctly.

The first 3 steps from the 6 presented above were part of the “legacy locking” requirements, only the last 3 steps were added for this new functionality.

The following WHO events trigger the lock function:

  • MenuItemClicked

  • ButtonClicked

  • ItemChanging

From any point in the code, if locking is needed (such as if an event is triggered that is not one of the 3 highlighted above), locking can be requested by calling the “Lock” method explicitly on the WHO.

Last updated