Current filter:
                                You should refresh the page.

                                This example illustrates one of the possible approaches to implementing an identifier field with sequential values. Alternate approaches are listed in the An overview of approaches to implementing a user-friendly sequential number for use with an XPO business class KB article.


                                This is a variation of 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 XPO example, which was specially adapted for XAF applications.

                                In particular, for better reusability and more smooth integration with the standard XAF CRUD Controllers, all the required operations to generate sequences are managed within the base persistent class automatically when a persistent object is being saved. For more developer convenience, this solution is organized as a reusable XAF module - GenerateUserFriendlyId.Module. This module consists of several key parts:

                                    - Sequence and SequenceGenerator are auxiliary classes that take the main part in generating user-friendly identifiers. Take special note that the SequenceGenerator.Initialize method must be called during your XAF application startup for the correct operation.

                                    - UserFriendlyIdPersistentObject is a base persistent class that subscribes to XPO's Session events and delegates calls to the core classes above. Normally, you must inherit your own business classes from this base class to get the described functionality in your project.

                                    - IUserFriendlyIdDomainComponent is a base domain component that should be implemented by all domain components that require the described functionality.

                                Check the original example description first for more information on the demonstrated scenarios and functionality.

                                Steps to implement
                                1. Copy and include the GenerateUserFriendlyId.Module project into your solution and make sure it is built successfully.  Invoke the Module or Application Designer for the YourSolutionName.Module/Module.xx  or YourSolutionName.Wxx/WxxApplication.xx files by double-clicking it in Solution Explorer. Invoke the Toolbox (Alt+X+T) and then drag & drop the GenerateUserFriendlyIdModule component into the modules list on the left.

                                2. For apps with no security or with the Client-Side Security (XPObjectSpaceProvider or SecuredObjectSpaceProvider):
                                In the YourSolutionName.Wxx/WxxApplication.xx files, modify the CreateDefaultObjectSpaceProvider method to call the SequenceGenerator.Initialize method as shown in the Demo.Wxx\WxxApplication.xx files:

                                protected override void CreateDefaultObjectSpaceProvider(CreateCustomObjectSpaceProviderEventArgs args) { IXpoDataStoreProvider dataStoreProvider = XPObjectSpaceProvider.GetDataStoreProvider(args.ConnectionString, args.Connection, true); // Web: // IXpoDataStoreProvider dataStoreProvider = GetDataStoreProvider(args.ConnectionString, args.Connection); GenerateUserFriendlyId.Module.SequenceGenerator.Initialize(dataStoreProvider); ... }

                                For apps with the Middle Tier Security (DataServerObjectSpaceProvider):
                                In the YourSolutionName.ApplicationServer project, locate and modify the serverApplication_CreateCustomObjectSpaceProvider or CreateDefaultObjectSpaceProvider  methods to call the SequenceGenerator.Initialize method in the same manner.

                                 If you are using pure XPO classes, then inherit your business classes to which you want to add sequential numbers from the module's UserFriendlyIdPersistentObject class. Declare a calculated property that uses the SequenceNumber property of the base class to produce an string identifier according to the required format:

                                public class Contact : GenerateUserFriendlyId.Module.BusinessObjects.UserFriendlyIdPersistentObject { [PersistentAlias("Concat('C',PadLeft(ToStr(SequentialNumber),6,'0'))")] public string ContactId { get { return Convert.ToString(EvaluateAlias("ContactId")); } }

                                If you are using DC interfaces, then implement the IUserFriendlyIdDomainComponent interface by your custom domain component:

                                public interface IDocument : GenerateUserFriendlyId.Module.BusinessObjects.IUserFriendlyIdDomainComponent { [Calculated("Concat('D',PadLeft(ToStr(SequentialNumber),6,'0'))")] string DocumentId { get; }

                                Additionally for DC, use the UserFriendlyIdPersistentObject as a base class during your custom domain component registration, e.g.:

                                XafTypesInfo.Instance.RegisterEntity("Document", typeof(IDocument), typeof(GenerateUserFriendlyId.Module.BusinessObjects.UserFriendlyIdPersistentObject));

                                Note that the sequential number functionality shown in this example does not work with DC shared parts , because it requires a custom base class, which is not allowed for shared parts.

                                4. By default, separate sequences are generated for each busienss object type. If you need to create multiple sequences for the same type, based on values of other object properties, override the GetSequenceName method and return the costructed sequence name. The Address class in this example uses separate sequences for each Province as follows:

                                protected override string GetSequenceName() { return string.Concat(ClassInfo.FullName, "-", Province.Replace(" ", "_")); }

                                5. For more information, download and review the Address, Contact, and IDocument types within the Demo.Module project. These are test business objects that demonstrate the use of the described functionality for XPO and DC respectively. Feel free to modify this example to add functionality as your business needs dictate.


                                IMPORTANT NOTES

                                1. As an alternative, you can implement much simpler solutions at the database level or by using the built-in DistributedIdGeneratorHelper.Generate method. Refer to the An overview of approaches to implementing a user-friendly sequential number for use with an XPO business class article for more details.

                                2.  In the Integrated Mode and middle-tier Application Server scenario the newly generated sequence number will appear in the DetailView only after a manual refresh (i.e., it will be empty right away after saving a new record), because the sequence is generated on the server side only and is not passed to the client. You can download a ready test project for these configurations here. See also the "Refresh the Identifier field value in UI" section in this KB article.
                                3. You can specify or seed the initial sequence value manually: either by editing the Sequence table in the database or using the standard XPO/XAF means by manipulating the Sequence objects, e.g.:

                                using(IObjectSpace os = Application.CreateObjectSpace(typeof(Sequence))) { Sequence sequence = os.FindObject<Sequence>(CriteriaOperator.Parse("TypeName=?", typeof(E2829).FullName)); sequence.NextSequence = 5; os.CommitChanges(); }

                                Your feedback is needed!
                                We would greatly appreciate it if you share your feedback here in comments or rather participate in this short survey (~3 min).