c# - 工作单元模式如何容纳对新聚合的引用?

标签 c# design-patterns domain-driven-design unit-of-work atomic

背景

据我了解,工作单元 (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 Remove 对已注册的所有操作的适当 IRepository 实例。我想说我上面概述的是对聚合根、存储库和 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.UserId 设置为 User.Id

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

最佳答案

Given the above separation of concerns and interpretation of aggregate boundaries, how would one provide transactional support to consumers who transactionally need to create an aggregate and save its repository-generated Id in another aggregate? E.g. how can I create a User and a Blog transactionally with Blog.UserId set to User.Id?

事情是 - 聚合也负责划定事务边界。这意味着 - 如果博客创建因某种原因失败,则无需同时创建用户和博客并回滚用户创建。

如果有这样的需求——你的聚合建模是错误的。


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

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

接口(interface)应该用于定义行为(角色)而不是什么实现类将持有(在这种情况下关于键类型的知识)。

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

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

继续学习。很快你就会停止滥用接口(interface)和泛型。 :)

关于c# - 工作单元模式如何容纳对新聚合的引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4743395/

相关文章:

c# - F# 属性与 C# 属性

c# - Google Play 游戏在 Social.localUser.Authenticate 上返回 false

design-patterns - 设计模式和框架有什么区别?

design-patterns - 什么是六边形设计模式

design-patterns - 贫血域模型是否意味着您不能将实用程序/支持类用作域模型的 "helpers"?

c# - 使用 Entity Framework 将项目添加到集合

c# - 如何使用 C# 更新 Active Directory 属性。

c# - 我不知道如何将子节点添加到 TreeView

java - 设计模式 - 使用通用对象来更新 GUI

java - 如何使用Spring Data Jpa将一个领域实体对象写入多个数据库表?