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.
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.
Install-Package 'Llamachant.ExpressApp.AutoIncrementingID'
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
});
Install-Package 'Llamachant.ExpressApp.AutoIncrementingID'
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
});
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.
using LlamachantFramework.AutoIncrementingID.Attributes;
private int _ID;
[AutoIncrement]
public int ID
{
get => _ID;
set => SetPropertyValue<int>(nameof(ID), ref _ID, value);
}
| 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 |
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;
}
| 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 |
Expressions such as LocalDateTimeToday() will not work as the trigger will convert this to the date and time of trigger creation.
You can group by multiple expressions for more complex scenarios
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.
using LlamachantFramework.AutoIncrementingID.Attributes;
private int _ID;
[AutoIncrement]
public int ID
{
get => _ID;
set => SetPropertyValue<int>(nameof(ID), ref _ID, value);
}
| 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 |
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;
}
| 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 |
Expressions such as LocalDateTimeToday() will not work as the trigger will convert this to the date and time of trigger creation.
You can group by multiple expressions for more complex scenarios
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 #.
| 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);
}
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;
}
| 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 |
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 #.
| 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);
}
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;
}
| 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 |
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.
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.
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
}
}
}
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.
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.
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
}
}
}