Autonumbering for collaboration
The basic principles of autonumbering are described in Autonumbering. This article describes the peculiarities of autonumbering during simultaneous work of several users.
Let us tackle this issue on the example of catalog (autonumbering is implemented in the same way for other object types).
The autonumbering algorithm is mainly based on the object data stored in a database table. To generate a code, 1C:Enterprise searches the catalog for the maximum code with the specified prefix. As indexing is always supported for "Code" field, the search runs quite fast.
Note that it only searches the existing records. If an object that had the maximum code was deleted, 1C:Enterprise provides this code upon the next request. However, if any object that did not have the maximum code was deleted, or some codes were skipped, 1C:Enterprise never provides the missing codes for new objects. If you want 1C:Enterprise to provide the missing codes, do not use the autonumbering feature. Instead, implement a custom numbering algorithm.
Note that codes are not generated during object creation. Some object creation scenarios actually do not include entering new data. For example, an object can be replicated from another infobase or from an external data source, and in both cases it comes with a code. Consequently, the code generation in such scenarios is just a waste of time because the generated code is immediately overwritten. This is why you need to assign a code explicitly using the SetNewCode() method. However, when an application user opens a new item form, the form extension automatically generates an item code. This is just a service operation supported by the form extension, it is similar to calling the SetNewCode() method in the form opening handler.
Thus, an application developer must call the method that sets a code exactly when it is necessary. Otherwise this would create an unnecessary database call, which might result in unwanted locks. We also recommend that you pay attention to choosing the optimal place for the SetNewCode() call. Calling this method in a transaction can lead to unwanted locks.
To ensure correct numbering in multiuser applications, 1C:Enterprise locks each new code from the moment when it is issued till the moment when an object is written (or when the CatalogObject value is removed from the memory).
//Fragment 1 Object1 = Catalogs.Products.CreateItem(); Object1.SetNewCode(); Message(Object1.Code); //4753 Object2 = Catalogs.Products.CreateItem(); Object2.SetNewCode(); Message(Object2.Code); //4754 //Fragment 2 Object1 = Catalogs.Products.CreateItem(); Object1.SetNewCode(); Message(Object1.Code); //4753 Object1 = Undefined; Object2 = Catalogs.Products.CreateItem(); Object2.SetNewCode(); Message(Object2.Code); //4753 //Fragment 3 Object1 = Catalogs.Products.CreateItem(); Object1.SetNewCode(); Message(Object1.Code); //4753 Object1.Write(); Object2 = Catalogs.Products.CreateItem(); Object2.SetNewCode(); Message(Object2.Code); //4754
In the first script fragment, the autonumbering issues a code to an object stored in the memory and locks this code. When it issues a code to the second object, it skips the locked code.
In the second script fragment, the same code is issued to both objects because the first object is no longer available when the code is issued to the second object. Note that this behavior is defined by setting Objects autonumbering mode configuration property to Release automatically. If this property is not set to Release automatically, the autonumbering does not reuse the first code, it sets code 4754 for Object2.
In the third code, autonumbering issues a different code to the second object because the first object is already written.
In general, the autonumbering searches for the maximum code, generates the next code based on this one, and checks whether this code is locked. If it is locked, it generates the next code and checks whether it is locked. It repeats this step until it finds a free code. Then it sets this code to a new item and locks it.
It is clear that this algorithm is mainly aimed at code generation for interactive data input. If a user starts entering an item in a form and then another user starts entering another item, 1C:Enterprise assigns different codes to these items.
If a catalog uses autonumbering and its code is blank, 1C:Enterprise generates a code when the catalog item is being written. Thus, there is no need to call SetNewcode() method when an item is created from 1C:Enterprise script. However, you might want to use this method to exclude the code generation from the transaction that writes an item.