良好的设计来跟踪领域模型的变化

时间:2015-12-08 19:06:00

标签: c# design-patterns nhibernate

我们有两个独立的现有应用程序,只能通过总线消息系统和数据库进行通信。现在我们想要通知第二个应用程序有关在db update之前或之后在第一个应用程序中对我们的域模型所做的任何更改:一旦我们知道存储器中存储了真正的更改或刚刚保存,我们就想发送特定的消息单独的申请。消息不表示进行了哪种更改。

一些注意事项:

  • 我们希望将我们的域模型保持简洁,我的意思是内部没有特定的业务逻辑,同时我们不希望向我们的数据层添加服务引用(存储库类列表)
  • 理想情况下,即使调用了存储库的Update方法,如果没有真正的更改进入数据库,我们也不希望发送消息。
  • 如果消息发送的时间早于将数据提交给db,即使它们最终被拒绝也是如此
  • 我们的域模型包含许多具有许多属性的对象,因此将OnPropertyChanged添加到每个属性会花费大量时间
  • 我们不希望在存储级别上实现通知系统
  • 我们希望以没有开发人员可以绕过此通知机制的方式构建我们的应用程序设计

您建议我们在应用程序设计方面使用哪些方法?数据层通过总线系统提交此类通知是否良好?我们怎么知道数据实际发生了变化:我们可以通过NHiberate会话知道它还是我们跟踪域模型中的变化?

2 个答案:

答案 0 :(得分:2)

  

数据层通过总线系统提交此类通知是否良好?

不,不是。虽然有些框架支持开箱即用,但自己拥有或写入通常是错误的。这里的问题有两个 -

  1. YAGNI - 当你预先设计一个系统时,你倾向于用过高的机制来压倒它,这反过来会影响系统的效率和简单性。
  2. 语境是关键!它太笼统了,没有一个存储库可以在没有上下文的情况下通知它所做的一切。每当您向表中插入一行以便更改UI时,请考虑通知,现在考虑从云中同步数据。数据膨胀与数据库和UI刷新率之间存在强烈的耦合,这显然是两个不同的事情。解决这个问题并保持连贯性就成了一种阻力。
  3.   

    我们怎么知道数据实际发生了变化:我们可以通过NHiberate会话知道它还是我们跟踪域模型中的变化?

    您对要求和此问题的陈述存在一些不一致之处。你这样表达了它 - "如果消息发送的时间早于将数据提交给数据库,即使它们最终被拒绝了,也没关系#34; 然后你说它与知道相关数据实际上已经改变了。

    无论如何,如果将数据直接保存到DB,它通常会返回一些指示,例如修改的行数。当使用像NHibernate这样的ORM框架时,您通常可以立即提交事务并获得相同的指示。

    在这两种方式中,只有当数据在数据库中实际更改时,如果另一个应用程序从同一个数据库中检索数据,您应该让其他应用程序知道。

      

    您建议我们在应用程序设计方面使用哪种方法?

    我们通过将事件作为逻辑过程的一部分发布而不是作为持久性的一部分来解决此问题,因为您可能有一些不需要通知的操作。如果您仍然希望在数据方面这样做,我建议不要在您的存储库中对其进行硬编码,而是使用Martin fowler的Unit of workTransaction script模式。它们将允许您决定哪些数据事务应该发布事件,哪些不是,以及何时发布。

答案 1 :(得分:1)

  

数据层通过以下方式提交此类通知是否良好?   公交系统?

不,但是如果您需要为每次更改提出这样的通知,并且如果您可以将这些事件绑定到系统的管道中而不需要更改所有存储库,那就OK了。

  

我们怎么知道数据实际发生了变化:我们可以通过NHiberate会话知道它还是我们必须跟踪域内的变化   模型?

此问题的最简单解决方案是使用interceptor or an event。 这样的事情可以解决你的问题,

活动

(请参阅this获取完整示例)

    public class ChangeEventListener : IFlushEntityEventListener
    {
        public SetModificationTimeFlushEntityEventListener()
        {
            CurrentDateTimeProvider = () => DateTime.Now;
        }

        public void OnFlushEntity(FlushEntityEvent @event)
        {
            var entity = @event.Entity;
            var entityEntry = @event.EntityEntry;

            if (entityEntry.Status == Status.Deleted)
            {
                //raise event
            }
            var trackable = entity as ITrackModificationDate;
            if (trackable == null)
            {
                return;
            }
            if (HasDirtyProperties(@event))
            {
                //raise event
            }
        }

    }

<强>拦截

public class NotificationInterceptor : EmptyInterceptor 
{

         public override bool OnFlushDirty(object entity, 
                                          object id, 
                          object[] currentState,
                          object[] previousState, 
                          string[] propertyNames,
                          IType[] types) 
        {
        //do check for changed states by comparing current and previous values, and raise event if changed
            return true
        }
 }