I've ran into a case where I was working with a database that was consumed by both Rails and Dapper. Rails was managing created_at and updated_at, not the database. So with the .net application I had to implement a solution that managed these and provided the ability to add additional business logic at these layers such as events.
I've included a basic example of how I handled this with a wrapper around Dapper Simple Crud for inserts and updates. This example does not include exposing the other critical methods from dapper and simplecrud such as Query, GET, Delete, etc. You will need to expose those at your discresion.
For safety ensure that you decorate your models created_at property with the attribute [Dapper.IgnoreUpdate]
[Table("examples")]
public partial class example
{
[Key]
public virtual int id { get; set; }
[Required(AllowEmptyStrings = false)]
[StringLength(36)]
public virtual string name { get; set; }
[Dapper.IgnoreUpdate]
public virtual DateTime created_at { get; set; }
public virtual DateTime updated_at { get; set; }
}
public class ExampleRepository : IExampleRepository
{
private readonly IYourDapperWrapper db;
public PartnerRepository(IYourDapperWrapper yourDapperWrapper){
if (yourDapperWrapper == null) throw new ArgumentNullException(nameof(yourDapperWrapper));
db = yourDapperWrapper;
}
public void Update(example exampleObj)
{
db.Update(exampleObj);
}
public example Create(example exampleObj)
{
var result = db.Insert(exampleObj);
if (result.HasValue) exampleObj.id = result.value;
return exampleObj;
}
}
public class YourDapperWrapper : IYourDapperWrapper
{
private IDbConnectionFactory db;
public YourDapperWrapper(IDbConnectionFactory dbConnectionFactory){
if (dbConnectionFactory == null) throw new ArgumentNullException(nameof(dbConnectionFactory));
db = dbConnectionFactory;
}
public int Insert(object model, IDbTransaction transaction = null, int? commandTimeout = null)
{
DateUpdate(model, true);
var results = Db.NewConnection().Insert(model, transaction, commandTimeout);
if (!results.HasValue || results == 0) throw new DataException("Failed to insert object.");
return results;
}
public int Update(object model, IDbTransaction transaction = null, int? commandTimeout = null)
{
DateUpdate(model, false);
var results = Db.NewConnection().Update(model, transaction, commandTimeout);
if (!results.HasValue || results == 0) throw new DataException("Failed to update object.");
return results;
}
private void DateUpdate(object model, bool isInsert)
{
model.GetType().GetProperty("updated_at")?.SetValue(model, DateTime.UtcNow, null);
if (isInsert) model.GetType().GetProperty("created_at")?.SetValue(model, DateTime.UtcNow, null);
}
}