【问题标题】:Are interceptors possible in ServiceStack.OrmLite?ServiceStack.OrmLite 中是否可以使用拦截器?
【发布时间】:2014-02-16 23:06:21
【问题描述】:

我想为 OrmLite 中的数据库插入或更新创建一个挂钩。

假设我想为插入到数据库中的每条记录写一个CreateDate,为每个没有数据库触发器或类似内容的更新写一个LastUpdateDate。如果我用包含新对象和更改对象的anyList 调用Db.Save<Anything>(anyList),我看不到这样做的方法。

我知道NHibernate does provide interceptors 在每个对象被持久化之前为其注入自定义逻辑。有什么方法可以在 ServiceStack.OrmLite 中实现这一点?

【问题讨论】:

  • 我还建议减少您问题的冗长,这仍然太多了。这并没有把事情弄清楚,如果有的话,它会更令人困惑。删除关于喜欢这项技术和成为“菜鸟”的序言,以及对 1、3、4 的引用。
  • 这不是重复的,达林。第一个是关于更改跟踪,这个页面是关于当对象被持久化到数据库时获取钩子的拦截器。是的,它们有点相关——这就是我最初在一篇文章中提出这些问题的原因。
  • @TheBert 我也更新了这个问题。现在这是一个明确且问得很好的问题。也许将您对 ServiceStack 的经验添加到您的 * 个人资料中,人们会在那里找到它。 :) 我希望这会有所帮助。
  • 目前不存在,但请随时add it as a feature request :)

标签: c# servicestack ormlite-servicestack


【解决方案1】:

我认为这是一个很好的功能,所以我只是 added support for Insert and Update Filters to OrmLite。所以现在你可以配置一个全局更新或插入过滤器:

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;
    }
};

所以现在 Created 和 Modified 日期字段将在实现 IAudit 并插入到任何 OrmLite 的 Typed API 的每一行上更新(即不是动态 SQL 或使用匿名类型的部分更新),例如:

表定义

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

验证

过滤器也可用于验证,抛出异常将阻止操作并冒泡异常,例如:

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

此功能现已在 ServiceStack's MyGet feed 中提供,并将在 NuGet 上的下一个 v4.0.11+ 版本中提供。

【讨论】:

  • 天啊,哇!你是开发者的野兽!非常感谢你!
【解决方案2】:

在 ServiceStack.OrmLite 中没有任何方法可以实现这一点。正如您所建议的那样,该功能仅是较重的 ORM(例如 NHibernate)的典型功能。

ServiceStack.OrmLite 旨在非常轻量级,因此provides a minimal API

您可以将诸如 NHibernate 之类的 ORM 与 ServiceStack 一起使用。我个人在我的 ServiceStack 项目中使用了一个名为 LightSpeed from Mindscape 的 ORM,它可以自动处理创建和更新时间戳,而无需任何代码挂钩。使用 ServiceStack REST 平台并不意味着您必须使用 ServiceStack ORM,如果它不合适的话。


正如@Mythz 建议的那样,您可以request that this feature is added

【讨论】:

    最近更新 更多