Scenario
Orders, articles or other business entities often require that you have user-friendly Id or Code fields that end-users can memorize and use during phone conversations. They are usually sequential, but some gaps can be allowed as well (e.g., when an order is deleted). Refer to this StackOverFlow thread for more information on this common scenario, and a possible implementation.
Steps to implement
1. Add a new business class to your platform-agnostic module, and call the static DevExpress.Persistent.BaseImpl.DistributedIdGeneratorHelper.Generate method from the AfterConstruction, OnSaving or other appropriate places within your persistent class or even Controller as shown in the Solution2.Module\BusinessObjects\Order.xx file. Depending on your business requirements, you can implement a readonly persistent or editable property where the generated value will be stored as well as check various conditions before generating the next sequence (e.g., string.IsNullOrEmpty(currentSequenceProperty) - to avoid double assignments, Session.IsNewObject(this) - to check whether the object is new, !(Session is NestedUnitOfWork) - to check whether the object is being saved to the database and not to the parent session, security system checks as per this blog post, etc.)
2. Build your platform-agnostic project and double-click on the Solution2.Module\Module.xx file to invoke the Module Designer;
3. Refer to the Exported Types section within the designer and expand the Referenced Assemblies | DevExpress.Persistent.BaseImpl node;
4. Select and press the space bar on the OidGenerator and ServerPrefix nodes to include these types into the business model of your module:
IMPORTANT NOTES
1. The DistributedIdGeneratorHelper class demonstrated in this solution creates the IDGeneratorTable and ServerPrefix tables to store the information about the last sequential number of a type.
Although this particular solution is simpler to implement and maintain (as it uses built-in XAF classes) than the How to generate and assign a sequential number for a business object within a database transaction, while being a part of a successful saving process (XAF) example, it is pretty safe and should also work in the most typical business scenarios (except for the middle-tier Application Server scenario, because the Session.DataLayer property is not initialized in this case).
2. You can find functional EasyTest scripts for this scenario in the Solution2.Module\FunctionalTests\E4904.ets file.
Question Comments
Added By: Gareth- at: 10/2/2013 5:58:17 AM
Thanks, works perfectly - I've seeded the ID by manually changing the [Oid] in the IDGeneratorTable, do I need to worry about the [OptimisicLockField] or will this update automatically?
Added By: Dennis (DevExpress Support) at: 10/2/2013 7:10:50 AM@Gareth: No, you do not need to care about the OptimisticLockField.
Added By: MohammedFarooq at: 12/2/2013 1:07:31 AMHi,
The code is really helpful but it increments the value of code even if the record is deleted! How can we stop the code to increase its value when a record is deleted?
Added By: MohammedFarooq at: 12/2/2013 1:25:16 AMI manage to figure out the solution. I have just added the IsDeleted checking and it worked like a charm!!!
Protected Overrides Sub OnSaving()
If (Not IsDeleted) Then
Me.codeCore = String.Format("N{0:D6}", DistributedIdGeneratorHelper.Generate(Me.Session.DataLayer, Me.GetType().FullName, String.Empty))
End If
MyBase.OnSaving()
End Sub
@Mohammed: Yes, your solution is correct. I will consider updating this example accordingly. Thanks for your input in this regard.
Added By: rushdan . at: 11/6/2014 12:02:48 AMHallo
I do not understand about explanation. What I know is, after I run the application, then save the data , it will execute Code number automatically.
Is it this example to show how to execute auto increase number ? Thanks
Added By: Dennis (DevExpress Support) at: 11/6/2014 2:00:43 AM@Rushdan: With the current implementation, the generation code is executed when the persistent object is being saved (OnSaving). I do not quite understand your last question. The functionality implemented in this example is well-detailed in the description and it can also be seen from simple code.
Added By: Andrew Bingham 2 at: 2/5/2015 12:40:25 AM"override its AfterConstruction method, as shown in the Solution2.Module\BusinessObjects\DomainObject1.xx file"
1. I cannot find the DomainObject1 file in the sample
2. The only BusinessObject is Order.cs which does not have an AfterConstruction method
3. What code need to go in AfterConstruction method?
4. What are the advantages / disadvantages compared to E2829?
1-3. I've corrected this misprint in the description.
3. This particular solution is simpler to implement than E2829.Added By: Vishwas Mokashi at: 4/21/2015 8:52:32 AM
Is there any provision so that we can restart the Sequence Number after say an Year is completed?. Also, any way to give the start number for the sequence?.
Added By: Dennis (DevExpress Support) at: 4/21/2015 8:57:35 AM@Vishwas: Sure, you can do this. Technically, the information about the last sequence number is stored in the Oid column of the IDGeneratorTable table with the help of the OidGenerator persistent class. You can modify this data using either ADO.NET or XPO means.
Added By: Vishwas Mokashi at: 4/21/2015 9:02:11 AMOk thanks Dennis...will try
Added By: MohammedFarooq at: 10/14/2015 2:37:53 AMDear Dennis,
I have applied this logic in my project which also has validation enabled. Now the issue is, if the validation of the document fails while saving the new number is generated. And when the user saves the document again then a new number is generated as well.
Added By: Dennis (DevExpress Support) at: 10/14/2015 2:58:59 AM @Mohammed: The original example has the if(string.IsNullOrEmpty(Code)) check that prevents multiple generations. Have you applied this code in your project? If this does not help, submit a separate ticket and attach your problematic sample so we can assist you further.