Question

I would like to create a hook for database inserts or updates in OrmLite.

Lets say I want to write a CreateDate for every record which is inserted to the database and a LastUpdateDate for every update without database triggers or anything like that. I see no way of doing this if I call Db.Save<Anything>(anyList) with anyList containing new and changed objects.

I know that NHibernate does provide interceptors to inject custom logic for each object before it gets persisted. Is there any way to achieve this in ServiceStack.OrmLite?

Was it helpful?

Solution

I thought this was a good feature that was missing so I've just added support for Insert and Update Filters to OrmLite. So now you can configure a global Update or Insert filter with:

public interface IAudit
{
    DateTime CreatedDate { get; set; }
    DateTime ModifiedDate { get; set; }
    string ModifiedBy { get; set; }
}

OrmLiteConfig.InsertFilter = (dbCmd, row) =>
{
    var auditRow = row as IAudit;
    if (auditRow != null)
    {
        auditRow.CreatedDate = auditRow.ModifiedDate = DateTime.UtcNow;
    }
};

OrmLiteConfig.UpdateFilter = (dbCmd, row) =>
{
    var auditRow = row as IAudit;
    if (auditRow != null)
    {
        auditRow.ModifiedDate = DateTime.UtcNow;
    }
};

So now the Created and Modified date fields will be updated on every row that implements IAudit and is inserted in any of OrmLite's Typed APIs (i.e. not dynamic SQL or partial updates using anon types), e.g:

Table Definition

public class AuditTableA : IAudit
{
    [AutoIncrement]
    public int Id { get; set; }
    public DateTime CreatedDate { get; set; }
    public DateTime ModifiedDate { get; set; }
    public string ModifiedBy { get; set; }
}

public class AuditTableB : IAudit
{
    [AutoIncrement]
    public int Id { get; set; }
    public DateTime CreatedDate { get; set; }
    public DateTime ModifiedDate { get; set; }
    public string ModifiedBy { get; set; }
}

var a = new AuditTableA();
var b = new AuditTableB();
db.Save(a);
db.Save(b);

var insertRowA = db.SingleById<AuditTableA>(a.Id);
var insertRowB = db.SingleById<AuditTableB>(b.Id);

//both insertRowA/insertRowB CreatedDate/ModifiedDate fields populated

Validation

The filters can also be used for validation where throwing an exception will prevent the operation and bubble the exception, e.g:

OrmLiteConfig.InsertFilter = OrmLiteConfig.UpdateFilter = (dbCmd, row) =>
{
    var auditRow = row as IAudit;
    if (auditRow != null)
    {
        if (auditRow.ModifiedBy == null)
            throw new ArgumentNullException("ModifiedBy");
    }
};

try
{
    db.Insert(new AuditTableA());
}
catch (ArgumentNullException) {
   //throws ArgumentNullException
}

db.Insert(new AuditTableA { ModifiedBy = "Me!" }); //succeeds

This feature is now available in ServiceStack's MyGet feed and will be available in the next v4.0.11+ release on NuGet.

OTHER TIPS

There isn't any way to achieve this in ServiceStack.OrmLite. That functionality is typical only of the heavier ORMs such as NHibernate, like you suggested.

ServiceStack.OrmLite is intended to be very lightweight, and as such provides a minimal API.

API

You can use an ORM such as NHibernate with ServiceStack. I personally use an ORM called LightSpeed from Mindscape in my ServiceStack projects, it can automatically take care of creation and update timestamps without any code hooks. Using the ServiceStack REST platform doesn't dictate that you have to use the ServiceStack ORM, if it isn't suitable.


As @Mythz suggests, you can request that this feature is added.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top