Auto Incrementing IDs
NuGet Package Details
Package Name
Llamachant.ExpressApp.AutoIncrementingID
Overview
This module provides automated sequential incrementation of integer fields using database triggers, with built-in support for Microsoft SQL Server. It is designed with extensibility in mind, allowing you to add support for other database providers as needed.
Beyond simple incrementation, the module also supports grouped incrementation scenarios. For instance, you can configure it to reset and increment values from 1 based on a specific grouping key such as the start of each calendar year. These incremented values can then be referenced in calculated fields or used to enforce custom numbering schemes.
🌟 Key Features
Installation
Step 1: Install the Module
Install-Package 'Llamachant.ExpressApp.AutoIncrementingID'
Step 2: Register the Module
public override void Setup(XafApplication application) {
base.Setup(application);
this.RequiredModuleTypes.Add(typeof(LlamachantFrameworkAutoIncrementingIDModule));
}
OR
services.AddXaf(Configuration, builder => {
builder.UseApplication<ExpressAppBlazorApplication>();
builder.Modules.AddLlamachantFrameworkAutoIncrementingIDModule(); //Add this line
});
AutoIncrement Attribute
Add the AutoIncrement attribute to an integer property to let the module know you want a trigger created. You can add optional arguments to group by properties or expressions.
Simple Incrementing
using LlamachantFramework.AutoIncrementingID.Attributes;
private int _ID;
[AutoIncrement]
public int ID
{
get => _ID;
set => SetPropertyValue<int>(nameof(ID), ref _ID, value);
}
Results
| Date Created | ID |
|---|---|
| Jan 1 @ 9:00 am | 1 |
| Jan 1 @ 9:05 am | 2 |
| Jan 2 @ 8:00 am | 3 |
| Jan 2 @ 1:00 pm | 4 |
Grouped Incrementing (By Day)
using LlamachantFramework.AutoIncrementingID.Attributes;
private int _ID;
[AutoIncrement("GetDate([CreatedOn])")]
public int ID
{
get => _ID;
set => SetPropertyValue<int>(nameof(ID), ref _ID, value);
}
private DateTime _CreatedOn;
public DateTime CreatedOn
{
get { return _CreatedOn; }
set { SetPropertyValue<DateTime>(nameof(CreatedOn), ref _CreatedOn, value); }
}
public override void AfterConstruction()
{
base.AfterConstruction();
_CreatedOn = DateTime.Now;
}
Results
| Date Created | ID |
|---|---|
| Jan 1 @ 9:00 am | 1 |
| Jan 1 @ 9:05 am | 2 |
| Jan 2 @ 8:00 am | 1 |
| Jan 2 @ 1:00 pm | 2 |
IMPORTANT
Expressions such as LocalDateTimeToday() will not work as the trigger will convert this to the date and time of trigger creation.
TIP
You can group by multiple expressions for more complex scenarios.
Custom IDs
You can use persistent alias properties to handle custom ID fields. In the example below, we are creating a calculated field that concatenates several strings together to produce a Ticket #.
Example: Ticket #: 20300218-0001
| Expression | Value for Feb 18, 2030 |
|---|---|
| 'Ticket #:' | Ticket #: |
| GETYEAR([CreatedOn]) | 2030 |
| PADLEFT(GETMONTH([CreatedOn]), 2, '0') | 02 |
| PADLEFT(GETDAY([CreatedOn]), 2, '0') | 18 |
| '-' | - |
| [ID] | 0001 |
using LlamachantFramework.AutoIncrementingID.Attributes;
[PersistentAlias(@"CONCAT(\
'TICKET #: ',\
GETYEAR([CreatedOn]),\
PADLEFT(GETMONTH([CreatedOn]), 2, '0'),\
PADLEFT(GETDAY([CreatedOn]), 2, '0'),\
'-',\
PADLEFT([ID], 4, '0'))")]
public string CustomID => Convert.ToString(EvaluateAlias(nameof(CustomID)));
private int _ID;
[Browsable(false)]
[AutoIncrement("GetDate([CreatedOn])")]
public int ID
{
get => _ID;
set => SetPropertyValue<int>(nameof(ID), ref _ID, value);
}
public override void AfterConstruction()
{
base.AfterConstruction();
_CreatedOn = DateTime.Now;
}
Results
| Date Created | ID | CustomID |
|---|---|---|
| Jan 1, 2030 @ 9:00 am | 1 | Ticket # 20300101-0001 |
| Jan 1, 2030 @ 9:05 am | 2 | Ticket # 20300101-0002 |
| Jan 2, 2030 @ 8:00 am | 1 | Ticket # 20300102-0001 |
| Jan 2, 2030 @ 1:00 pm | 2 | Ticket # 20300102-0002 |
Customizing Triggers
Triggers are created as part of the XAF ModuleUpdater process.
This module collects all properties that have an AutoIncrement attribute and generates an SQL statement for creating the trigger. You can override this SQL to generate your own trigger as needed.
TIP
If you want to support other database providers that use triggers, you'll need to provide the correct commands to create triggers for each property. This lets the module work with different types of databases and their specific syntax.
Subscribe to TriggerCreating
In your Module.cs file, handle the application's SetupComplete event to locate the LlamachantFrameworkAutoIncrementingIDModule. Once located, subscribe to its TriggerCreating event to customize or extend the behavior of the auto-increment trigger generation.
using LlamachantFramework.AutoIncrementingID;
public sealed class MyModule : ModuleBase {
public override void Setup(XafApplication application)
{
base.Setup(application);
application.SetupComplete += Application_SetupComplete;
}
private void Application_SetupComplete(object sender, EventArgs e)
{
LlamachantFrameworkAutoIncrementingIDModule.FindModule(Application.Modules).TriggerCreating += ExpressAppWinModule_TriggerCreating;
}
private void ExpressAppWinModule_TriggerCreating(object sender, AutoIncrementingID.Updaters.TriggerEventArgs e)
{
if (e.ObjectType.Type == typeof(Client) && e.Member.Name == nameof(Client.ID))
{
e.TriggerCreationQuery = "...custom trigger creation sql...";
e.TriggerExistenceQuery = "...custom trigger existence query..."; //You can set this to null if needed
}
}
}