背景

据我了解,工作单元(UoW)模式实质上提供了事务语义。换句话说,给定存储库保留的聚合域,UoW类允许该域的使用者将存储库方法的调用注册到原子操作中。说我们有:

interface IAggregate<TKey> {
    TKey Id { get; }
}

interface IRepository<TEntity, in TKey> where TEntity : IAggregate<TKey> {
    TEntity Get(TKey id);
    void Save(TEntity entity);
    void Remove(TEntity entity);
}

interface IUnitOfWork {
    void RegisterSave<TEntity>(TEntity entity);
    void RegisterRemove<TEntity>(TEntity entity);
    void RegisterUnitOfWork(IUnitOfWork uow);
    void Commit();
    void Rollback();
}


假定IRepository的实现使用关系数据库,并且IUnitOfWork.Commit的实现仅与数据库建立事务,然后继续在适当的Save实例上为所有操作执行调用RemoveIRepository已注册。我想说的是,我概述了聚合根,存储库和UoW模式的标准,直接解释(尽管NHibernate / EF及其所有膨胀的荣耀)。

过去,我将聚合根边界的概念解释为意味着从一个聚合到另一个聚合的引用应通过源聚合上目标聚合的Id属性来客观化。例如:

class User : IAggregate<int> {
  int Id { get; private set; }
}

class Blog : IAggregate<int> {
  int Id { get; private set; }
  int AuthorUserId { get; set; }
}




鉴于以上关注点分离和汇总边界的解释,一个人如何为需要交易创建汇总并将其存储库生成的ID保存在另一个汇总中的消费者提供交易支持?例如。如何在User设置为Blog的情况下通过事务创建Blog.UserIdUser.Id

我已经提出了一些答案(标记为社区Wiki),但无论如何还是在这里发布我的问题,以征求反馈和更多答案。

最佳答案

鉴于以上关注点分离和汇总边界的解释,一个人如何为需要交易创建汇总并将其存储库生成的ID保存在另一个汇总中的消费者提供交易支持?例如。如何在Blog.UserId设置为User.Id的情况下通过事务创建用户和博客?


事情是-聚合也有责任划定交易界限。这意味着-如果Blog创建由于某种原因失败,则无需同时使用Blog创建用户和回滚User创建。

如果有这样的需求-您正在建模聚合错误。



只是发表一些可能有用的快速评论...

interface IAggregate<TKey> {
    TKey Id { get; }
}


应该使用接口来定义行为(角色),而不是用于定义实现类将持有的接口(在这种情况下,有关密钥类型的知识)。

谷歌搜索速度不够快,无法找到正确的解释,为什么会这样呢...
稍后再试。

interface IRepository<TEntity, in TKey> where TEntity : IAggregate<TKey> {
  TEntity Get(TKey id);
  void Save(TEntity entity);
  void Remove(TEntity entity);
}


避免使用generic repositories

interface IUnitOfWork {
  void RegisterSave<TEntity>(TEntity entity);
  void RegisterRemove<TEntity>(TEntity entity);
  void RegisterUnitOfWork(IUnitOfWork uow);
  void Commit();
  void Rollback();
}


避免使用unit of work(这可以解决您的问题)。

interface IAggregate<TSelf> where TSelf : IAggregate<TSelf>
{
    IKey<TSelf> Id { get; }
}


保持学习。很快,您将停止滥用接口和泛型。 :)

07-24 19:17
查看更多