C# OnPost事件在提交之前运行

C# OnPost事件在提交之前运行,c#,nhibernate,C#,Nhibernate,假设我有一些像这样的标准NHibernate代码,它写入SQL数据库: using (var session = SessionFactory.OpenSession()) { using (var tx = session.BeginTransaction()) { var customer = session.Get<Customer>(id); customer.Property1 = "new value"; customer.Pr

假设我有一些像这样的标准NHibernate代码,它写入SQL数据库:

using (var session = SessionFactory.OpenSession())
{
  using (var tx = session.BeginTransaction())
  {
      var customer = session.Get<Customer>(id);
      customer.Property1 = "new value";
      customer.Property2 = "new value";
      tx.Commit();
  }
}
如果要将第一个代码片段更改为insert,则将运行:

 public void OnPostInsert(PostInsertEvent postInsertEvent)
        {
            if (postInsertEvent.Entity.GetType() == typeof(Customer))  
            {
                var customer = (Customer)postInsertEvent.Entity;
                customerCopyRepository.Insert(customer);
            }
        }
当发生删除时,将运行:

public void OnPostDelete(PostDeleteEvent postDeleteEvent)
        {
            if (postDeleteEvent.Entity.GetType() == typeof(Customer)) 
            {
                var customer = (Customer)postDeleteEvent.Entity;
                customerCopyRepository.Delete(customer.Id);
            }
        }
CustomerCopyRepository被注入到类构造函数中

这是非常好的工作。我唯一的问题是,上面的每个事件似乎都是在数据提交到数据库之前运行的。因此,可能出现以下情况:

1) 将客户写入NoSQL数据库

2) 客户未写入SQL数据库(因为SQL错误)


有什么方法可以防止这种情况发生吗?

我有完全相同的情况(与ElasticSearch同步),最后我使用了RegisterSynchronization方法:

private void Sync(IPostDatabaseOperationEventArgs e)
{
    e.Session.Transaction.RegisterSynchronization(new AfterTransactionCompletes(success =>
    {
        if (!success)
            return;

        // Do your stuff
    }));
}

这似乎是服务总线的一个场景。或者触发某种域事件,如OnSaved,如果NoSql端的更新失败,它将被拾取并移动到NoSql repo,然后重试并发送一个错误队列。@Fran,如果您不能使用post(即PostUpdate、PostDelete等),为什么我的帖子中的事件会存在?谢谢。我并不是说你不能使用它们,我只是说使用一个完整的ESB,带有重试和一个错误队列,最终的一致性是一个更好的解决方案,因为我们对事件有很多原因。现在,任何故障都会使您的系统处于不一致的状态,并且您不会收到已完成或出错的消息。那么,您的系统是如何恢复的呢?我使用EventListeners,但作为我数据库中触发器的替代,它可以在预插入或预更新时更新给定实体上的审核字段。@Fran,如果在预插入/预更新运行后数据库插入/更新未运行,会发生什么情况?再次感谢,谢谢。如果“做你的事”下的代码失败了怎么办?您可以回滚事务吗?否,此方法在事务完成后调用。我们也考虑过这一点,但由于我们的SQL数据库是唯一的真相来源,我们决定接受这一差距。此外,我认为确保所有数据存储的所有事务都已完成,并对所有事务都有备用机制,这将非常复杂。您如何补偿故障?您是否稍后重试?
private void Sync(IPostDatabaseOperationEventArgs e)
{
    e.Session.Transaction.RegisterSynchronization(new AfterTransactionCompletes(success =>
    {
        if (!success)
            return;

        // Do your stuff
    }));
}