DDD理论学习系列(12)– 仓储。DDD理论学习系列(12)– 仓储。

DDD理论学习系列——案例与目录

DDD理论学习系列——案例与目录



1. 引言

DDD中Repository斯单词,主要发生一定量种翻译:资源库仓储,本文取仓储之译。

说及囤,我们自然就想开了储藏室,仓库一般用来存放在货物,而储藏室一般由仓库管理员来管理。当工厂生产了一致批货物经常,只需要交仓库管理员即可,他当货物的堆积;当得发货的时段,仓库管理员负责从仓库中捡货进行商品出库处理。当得库存盘点时,仓库管理员负责把关货物状态与库存。换句话说,仓库管理员负责了货的出入库管理。通过储藏室管理员是角色,保证了库房和工厂的独立性,工厂只待负生产即可,而关于商品如何存放工厂无需关注。

若是我们而讲的蕴藏就象是于仓库管理员,只不过它担负之不再是商品之军事管制,而是聚合的保管,仓储介于领域模型与数据模型之间,主要用来汇的持久化和查找。它隔离了世界模型和数据模型,以便我们关心为世界模型如果非待考虑怎样开展持久化。

1. 引言

DDD中的Repository,主要发生有限种植翻译:资源库仓储,本文取仓储之译。

说到囤,我们肯定就是想开了储藏室,仓库一般用来存放在货物,而仓库一般由仓库管理员来管理。当工厂生产了平批判货物时,只待交仓库管理员即可,他承受货物的积;当得发货的上,仓库管理员负责从仓库被捡货进行商品出库处理。当用库存盘点时,仓库管理员负责把关货物状态和库存。换句话说,仓库管理员负责了商品的出入库管理。通过储藏室管理员是角色,保证了仓库和工厂的独立性,工厂只待承担生产即可,而至于商品如何存放工厂无需关注。

一旦我辈若讲话的仓储就类似于仓库管理员,只不过它负责之不再是货物的管住,而是聚合的田间管理,仓储介于领域模型和数据模型之间,主要用于汇的持久化和搜索。它隔离了世界模型和数据模型,以便我们关注被世界模型如果休欲考虑什么进展持久化。

2. DDD中的储存

2. DDD中之贮存

2.1. 存储的成团特性

存储代表一个汇的集聚,其表现与.Net集合一样,仓储用来存储和去聚合,但同时提供对聚合的显式查询以及集中。

2.1. 仓储的集纳特性

囤代表一个汇的集聚,其行与.Net集合一样,仓储用来储存和去聚合,但与此同时提供对聚合的显式查询以及集中。

2.2. 储存及数量访问层的别

  1. 囤限定了只能通过聚合根来持久化和找领域对象,以保险有改变和无变性由汇处理。
  2. 囤通过隐形聚合持久化和找的底层技术实现世界层的之持久化无关性(即世界层不欲知道什么样持久化领域对象)。
  3. 囤于数据模型和世界模型定义了一个边际。

2.2. 存储和数码访问层的区别

  1. 积存限定了不得不通过聚合根来持久化和搜索领域对象,以保险有改变和免变性由汇处理。
  2. 积存通过逃匿聚合持久化和摸索的脚技术实现世界层的的持久化无关性(即世界层不需要明白如何持久化领域对象)。
  3. 储存以数据模型和领域模型定义了一个境界。

2.3. 囤积举例

脚我们首先来拘禁一个简仓储的概念:

namespace DomainModel
{
 public interface ICustomerRepository
 {
 Customer FindBy(Guid id);
 void Add(Customer customer);
 void Remove(Customer customer);
 }
}

通常来说,仓储由应用服务层调用。仓储定义应用服务执行工作用例时要的有所的多寡访问方法。而仓储的落实日常在基础架构层,由持久化框架来支持。以下的贮存实现是凭借ORM框架Nhibernate的ISession接口,它去一个底网关角色,负责领域模型和数据模型的炫耀。

namespace Infrastructure.Persistence {
    public class CustomerRepository : ICustomerRepository {
        private ISession _session;
        public CustomerRepository (ISession session) {
            _session = session;
        }
        public IEnumerable<Customer> FindBy (Guid id)
            return _session.Load<Order> (id);
        }

        public void Add (Customer customer) {
            _session.Save (customer);
        }

        public void Remove (Customer customer) {
            _session.Delete (customer);
        }
    }
}

从今者我们好观看,将世界模型的持久化转移到基础设备层,隐藏了世界模型的技能复杂,从而使世界对象会专注于工作概念与逻辑。

2.3. 仓储举例

脚我们第一来拘禁一个概括仓储的概念:

namespace DomainModel
{
 public interface ICustomerRepository
 {
 Customer FindBy(Guid id);
 void Add(Customer customer);
 void Remove(Customer customer);
 }
}

习以为常来说,仓储由应用服务层调用。仓储定义应用服务执行工作用例时欲之所有的数额访问方法。而仓储的兑现日常在基础架构层,由持久化框架来支持。以下的存储实现是负ORM框架Nhibernate的ISession接口,它去一个底网关角色,负责领域模型和数据模型的映射。

namespace Infrastructure.Persistence {
    public class CustomerRepository : ICustomerRepository {
        private ISession _session;
        public CustomerRepository (ISession session) {
            _session = session;
        }
        public IEnumerable<Customer> FindBy (Guid id)
            return _session.Load<Order> (id);
        }

        public void Add (Customer customer) {
            _session.Save (customer);
        }

        public void Remove (Customer customer) {
            _session.Delete (customer);
        }
    }
}

由上面我们可以看出,将世界模型的持久化转移到基础设备层,隐藏了世界模型的技巧复杂,从而使世界对象会专注于业务概念与逻辑。

2.4. 储存的误解

存储为存在许多误解,许多人口以为其是未必要的空洞。当使用被简单的圈子模型时,可以直接以持久化框架来拓展数据看。然而当对复杂的领域模型进行建模时,仓储是范的扩充,它标志聚合检索的打算,可以针对世界模型进行有义的读写,而休是一个艺框架。

也有诸多口看仓储是一模一样种反模式,因为该藏匿了根基持久化框架的效能。而恰巧这多亏仓储的要义。基础持久化框架提供了放的接口用于对数据模型的寻找和修改,而仓储通过利用定义的命名查询方式来界定对聚集的看。通过使查询显式化,就再便于调整查询,且更关键的凡储存明确了询问的打算,便于领域专家理解。举个例子:我们以蕴藏中定义了一个方法GetAllActiveUsers()与sql语句select * from users where isactive = 1var users =db.Users.Where(u=>u.IsActive ==1)相对而言,很强烈仓储的艺术命名就能够被咱掌握了询问的企图:查询所有处于Active状态的用户。除查询,仓储仅暴露必要的持久化方法而未是供有的CURD方法。

2.4. 存储的误解

仓储为有重重误解,许多口看那是休必要的肤浅。当以为简单的小圈子模型时,可以直接用持久化框架来展开多少看。然而当对复杂的园地模型进行建模时,仓储是范的扩张,它标志聚合检索的企图,可以本着世界模型进行有意义的读写,而未是一个技术框架。

否有不少总人口觉着仓储是如出一辙种植反模式,因为该隐藏了根基持久化框架的法力。而恰恰这正是仓储的要领。基础持久化框架提供了开的接口用于对数据模型的检索和改,而仓储通过利用定义之命名查询艺术来界定对聚集的拜会。通过使查询显式化,就再便于调整查询,且再次要紧的凡储存明确了查询的打算,便于领域专家理解。举个例子:我们在存储中定义了一个措施GetAllActiveUsers()与sql语句select * from users where isactive = 1var users =db.Users.Where(u=>u.IsActive ==1)对比,很显著仓储的措施命名就可知让我们懂得了查询的图:查询所有处于Active状态的用户。除却查询,仓储仅暴露必要的持久化方法要非是供具有的CURD方法。

2.5. 仓储的要点

储存的要并无是如果代码更易测试,也无是为好切换底层的持久化存储方。当然,在某种程度上,这吗的确是储存所带的利好。囤的要领是涵养您的世界模型和技能持久化框架的独立性,这样您的领域模型可以凝集来自底层持久化技术之熏陶。如果没有仓储这无异于重叠,你的持久化基础设备或者会见泄露及世界模型中,并影响世界模型完整性和最后一致性。

2.5. 存储的要领

积存的中心思想并无是如代码更爱测试,也未是为着便于切换底层的持久化存储方。当然,在某种程度上,这吗确是储存所带的利好。仓储的要点是保持您的天地模型与技能持久化框架的独立性,这样你的圈子模型可以凝集来自底层持久化技术的熏陶。如果没仓储这同交汇,你的持久化基础设备或会见泄露及世界模型中,并影响世界模型完整性和最终一致性。

3. 天地模型 VS 数据模型

假若选择涉及项目数据库作为持久化存储,我们得以因ORM框架来贯彻世界模型与数据模型之间的投和持久化操作。

假设ORM又是呀也?

照文章开始中之例证,如果存储对承诺仓库管理员的角色,那ORM就一定给仓库机器人,而储藏室就相当给数据库。为了有利于不同商品之归类存放,对仓进行分区,分区就相当给数据表。当企业吸收一画订单做发货处理时,销售员将发货通知单告知仓库管理员,仓库管理员再分配ORM机器人进行捡货。很显著,ORM机器人必须能辨识发货通知单,将发货通知不过着之货色对承诺交库房被储存的货品。这中发货通知只是就一定给世界模型,而仓库着存储的货虽属数据模型。

信任基于上面的比方,我们针对ORM有矣骨干的认。ORM,全称是Object
Relational
Mapping,对象关联映射。ORM的前提是,将目标的性质映射到数据库字段,将目标中的援映射到数码库表的关系。换句话说,ORM负责将代码中定义的靶子同涉及映射到数据库的阐发结构被去,并以展开多少看时再也将说明数据映射到代码中定义之对象,借助ORM我们不欲去手动写SQL语句就得做到多少的增删改查。ORM就抽象了关系数据模型,它只是为面向对象的方来表示数据模型,以造福我们于代码中轻轻松松地拍卖数量。

脚我们来探索一下数据模型与世界模型的异同。关系数据库中的数据模型,它由表和排成,它只是略的存储结构,用于保存领域模型有时间点的状态。数据模型可以分流于几乎单说明还几单数据库中。此外,可以使多种形式的持久化存储,例如文件、web服务器、关系数据库或NoSQL。领域模型是指向问题域的肤浅,具有丰富的言语与表现,由实体和价值对象成。对于一些世界模型,可能跟数据模型相似,甚至同一,但于概念上它是异常例外之。ORM与世界模型无关。仓储的意图就是是将世界模型与数据模型分开,而不是让它模糊化一个模子。ORM不是储存,但是仓储可以下ORM来持久化领域对象的状态。

图片 1

要是您的天地模型和您的数据模型类似,ORM可以一直照射领域模型到多少存储,否则,则需要针对ORM进行额外的炫耀配置。

3. 领域模型 VS 数据模型

要选择涉及项目数据库作为持久化存储,我们好凭ORM框架来促成世界模型和数据模型之间的映照和持久化操作。

倘ORM又是什么呢?

据文章开始中之事例,如果存储对诺仓库管理员的角色,那ORM就相当给仓库机器人,而储藏室就一定给数据库。为了便利不同商品之归类存放,对库房进行分区,分区就相当给数据表。当企业接受一画订单做发货处理时,销售员将发货通知单告知仓库管理员,仓库管理员再分配ORM机器人进行捡货。很强烈,ORM机器人必须能辨识发货通知单,将发货通知不过中的货品对承诺交仓库被储存的货物。这间发货通知只是就一定给天地模型,而仓库着蕴藏的货色虽属数据模型。

信任基于上面的比喻,我们针对ORM有矣基本的认识。ORM,全称是Object
Relational
Mapping,对象关系映射。ORM的前提是,将对象的性质映射到数据库字段,将目标中的援映射到数码库表的涉。换句话说,ORM负责将代码中定义的目标同干映射到数据库的申结构面临失,并当展开数量访问时再也用表明数据映射到代码中定义的靶子,借助ORM我们无需去手动写SQL语句就得好多少的增删改查。ORM就抽象了关系数据模型,它仅仅是为面向对象的措施来代表数据模型,以好我们以代码中轻松地拍卖多少。

下我们来探索一下数据模型与世界模型的异同。关系数据库中的数据模型,它由表和排成,它只是简单的囤积结构,用于保存领域模型有时间点的状态。数据模型可以散开在几乎独说明还几个数据库中。此外,可以以多种形式的持久化存储,例如文件、web服务器、关系数据库或NoSQL。领域模型是针对性问题域的架空,具有丰富的言语及行事,由实体和价值对象成。对于一些天地模型,可能同数据模型相似,甚至同,但在概念上它们是深差的。ORM与天地模型无关。仓储的用意就是拿世界模型和数据模型分开,而不是受它们模糊化一个模型。ORM不是储存,但是仓储可以使ORM来持久化领域对象的状态。

如若您的园地模型和汝的数据模型类似,ORM可以一直照射领域模型到数量存储,否则,则需对ORM进行额外的照配置。

4. 囤积的定义及落实

上面吧涉及过,我们一般以世界层定义仓储接口,在基础设备层实现仓储,以切断领域模型和数据模型。

4. 储存的概念和兑现

方也提到了,我们一般在圈子层定义仓储接口,在基础设备层实现仓储,以切断领域模型与数据模型。

4.1. 囤积方法需要明确

仓储是法达成是天地模型和持久化存储之间显然的契约,仓储定义的接口方法不但是CURD方法。它是世界模型的壮大,并因领域专家所理解的术语编写。仓储接口的定义应该因应用程序的用例需求来创造,而休是于接近CURD的数目看角度来构建。

咱来拘禁同样截代码:

namespace DomainModel {
    public interface ICustomerRepository {
        Customer FindBy (Guid id);
        IEnumerable<Customer> FindAllThatMatch (Query query);
        IEnumerable<Customer> FindAllThatMatch (String hql);
        void Add (Customer customer);
    }
}

如上仓储定义了一个FindAllThatMatch艺术以支撑客户端以其他方式查询领域对象。这个点子的规划思想无可置否,灵活且可以扩大,但是其并无明确的表明查询的作用,我们即便夺了对查询的操纵。为了真正了解如何采取这些办法,开发人员需要跟相关调用堆栈,才能够知悉方法的图,更别说出现性能问题常常怎样下手优化了。因为仓储定义的接口方法过于厚实泛且不现实,它模糊了世界的底概念,所以定义这样的一个接口方法是虚幻的。

咱们得如下改造:

namespace DomainModel {
    public interface ICustomerRepository {
        Customer FindBy (Guid id);
        IEnumerable<Customer> FindAllThatAreDeactivated ();
        IEnumerable<Customer> FindAllThatAreOverAllowedCredit ();
        void Add (Customer customer);
    }
}

透过以上改造,我们通过措施的命名来家喻户晓询问的作用,符合通用语言的正式。

4.1. 囤积方法要明确

存储是标准化及是圈子模型和持久化存储之间明显的契约,仓储定义的接口方法不但是CURD方法。它是小圈子模型的恢弘,并坐领域专家所知晓的术语编写。仓储接口的定义应该根据应用程序的用例需求来创造,而休是自接近CURD的数量访问角度来构建。

咱来拘禁一样段落代码:

namespace DomainModel {
    public interface ICustomerRepository {
        Customer FindBy (Guid id);
        IEnumerable<Customer> FindAllThatMatch (Query query);
        IEnumerable<Customer> FindAllThatMatch (String hql);
        void Add (Customer customer);
    }
}

上述仓储定义了一个FindAllThatMatch方法以支撑客户端以其它方法查询领域对象。这个点子的计划性思想无可置否,灵活且可以扩大,但是它并不曾显著的标志查询的意,我们便失去了针对性查询的决定。为了真正了解怎么利用这些艺术,开发人员需要跟相关调用堆栈,才能够知悉方法的打算,更别说出现性能问题经常怎么入手优化了。因为仓储定义之接口方法过于厚实泛且不现实,它模糊了世界的之定义,所以定义这样的一个接口方法是空虚的。

咱得以如下改造:

namespace DomainModel {
    public interface ICustomerRepository {
        Customer FindBy (Guid id);
        IEnumerable<Customer> FindAllThatAreDeactivated ();
        IEnumerable<Customer> FindAllThatAreOverAllowedCredit ();
        void Add (Customer customer);
    }
}

经以上改造,我们经过艺术的命名来家喻户晓询问的意,符合通用语言的正统。

4.2. 泛型仓储

在实践中我们或会见意识,为各一个汇定义一个囤积会招更代码,因为多数之多寡操作都是看似之。为了代码用,泛型仓储就应时而生。

泛型仓储举例:

namespace DomainModel {
    public interface IRepository<T> where T : EntityBase {
        T GetById (int id);
        IEnumerable<T> List ();
        IEnumerable<T> List (Expression<Func<T, bool>> predicate);
        void Add (T entity);
        void Delete (T entity);
        void Edit (T entity);
    }

    public abstract class EntityBase {
        public int Id { get; protected set; }
    }
}

泛型仓储实现:

namespace Infrastructure.Persistence {
    public class Repository<T> : IRepository<T> where T : EntityBase {
        private readonly ApplicationDbContext _dbContext;
        public Repository (ApplicationDbContext dbContext) {
            _dbContext = dbContext;
        }
        public virtual T GetById (int id) {
            return _dbContext.Set<T> ().Find (id);
        }

        public virtual IEnumerable<T> List () {
            return _dbContext.Set<T> ().AsEnumerable ();
        }

        public virtual IEnumerable<T> List (Expression<Func<T, bool>> predicate) {
            return _dbContext.Set<T> ()
                .Where (predicate)
                .AsEnumerable ();
        }

        public void Insert (T entity) {
            _dbContext.Set<T> ().Add (entity);
            _dbContext.SaveChanges ();
        }

        public void Update (T entity) {
            _dbContext.Entry (entity).State = EntityState.Modified;
            _dbContext.SaveChanges ();
        }

        public void Delete (T entity) {
            _dbContext.Set<T> ().Remove (entity);
            _dbContext.SaveChanges ();
        }
    }
}

通过定义泛型仓储和默认的落实,很挺程度达到展开了代码用。但是,尝试以泛型仓储应用拥有存储并无是一个好之主。对于简易的会师我们得直接使用泛型仓储来简化代码。但对复杂的汇聚,泛型仓储可能就是见面无极端符合,如果根据泛型仓储的法子进行多少看,就会搅乱对聚集的拜会意图。

对此复杂的联谊,我们可以另行定义:

namespace DomainModel {
    public interface ICustomerRepository {
        Customer FindBy (Guid id);
        IEnumerable<Customer> FindAllThatAreDeactivated ();
        void Add (Customer customer);
    }
}

于贯彻时,我们得以引用泛型仓储来避免代码重复。

namespace Infrastructure.Persistence {
    public class CustomerRepository : ICustomerRepository {
        private IRepository<Customer> _customersRepository;
        public Customers (IRepository<Customer> customersRepository) {
            _customersRepository = customersRepository;
        }
        // ....
        public IEnumerable<Customer> FindAllThatAreDeactivated () {
            _customersRepository.List(c => c.IsActive == false);
        }
        public void Add (Customer customer) {
            _customersRepository.Add (customer);
        }
    }
}

由此这种方法,我们就算明确了询问了作用,又简化了代码。

4.2. 泛型仓储

在实践中我们兴许会见意识,为各个一个会合定义一个囤会招致更代码,因为多数底数量操作都是类似之。为了代码用,泛型仓储就应时而生。

泛型仓储举例:

namespace DomainModel {
    public interface IRepository<T> where T : EntityBase {
        T GetById (int id);
        IEnumerable<T> List ();
        IEnumerable<T> List (Expression<Func<T, bool>> predicate);
        void Add (T entity);
        void Delete (T entity);
        void Edit (T entity);
    }

    public abstract class EntityBase {
        public int Id { get; protected set; }
    }
}

泛型仓储实现:

namespace Infrastructure.Persistence {
    public class Repository<T> : IRepository<T> where T : EntityBase {
        private readonly ApplicationDbContext _dbContext;
        public Repository (ApplicationDbContext dbContext) {
            _dbContext = dbContext;
        }
        public virtual T GetById (int id) {
            return _dbContext.Set<T> ().Find (id);
        }

        public virtual IEnumerable<T> List () {
            return _dbContext.Set<T> ().AsEnumerable ();
        }

        public virtual IEnumerable<T> List (Expression<Func<T, bool>> predicate) {
            return _dbContext.Set<T> ()
                .Where (predicate)
                .AsEnumerable ();
        }

        public void Insert (T entity) {
            _dbContext.Set<T> ().Add (entity);
            _dbContext.SaveChanges ();
        }

        public void Update (T entity) {
            _dbContext.Entry (entity).State = EntityState.Modified;
            _dbContext.SaveChanges ();
        }

        public void Delete (T entity) {
            _dbContext.Set<T> ().Remove (entity);
            _dbContext.SaveChanges ();
        }
    }
}

由此定义泛型仓储及默认的实现,很老程度达进展了代码用。但是,尝试以泛型仓储应用具有存储并无是一个吓的意见。对于简易的聚众我们得以一直下泛型仓储来简化代码。但对复杂的聚合,泛型仓储可能就是会无极端符合,如果根据泛型仓储的方进行多少访问,就会搅乱对聚集的看意图。

对此复杂的集,我们得以另行定义:

namespace DomainModel {
    public interface ICustomerRepository {
        Customer FindBy (Guid id);
        IEnumerable<Customer> FindAllThatAreDeactivated ();
        void Add (Customer customer);
    }
}

当贯彻时,我们好引用泛型仓储来避免代码重复。

namespace Infrastructure.Persistence {
    public class CustomerRepository : ICustomerRepository {
        private IRepository<Customer> _customersRepository;
        public Customers (IRepository<Customer> customersRepository) {
            _customersRepository = customersRepository;
        }
        // ....
        public IEnumerable<Customer> FindAllThatAreDeactivated () {
            _customersRepository.List(c => c.IsActive == false);
        }
        public void Add (Customer customer) {
            _customersRepository.Add (customer);
        }
    }
}

通过这种方法,我们不怕明确了询问了作用,又简化了代码。

4.3. IQueryable Vs IEnumerable

每当概念仓储方法的回到值时,我们也许会见较疑惑,是应一直返回数据(IEnumerable)还是回到查询(IQueryable)以便进行更加的细化查询?返回IEnumerable见面于安全,但IQueryable供了再次好之灵活性。事实上,如果采取IQueryable用作返回值,我们特提供相同种读取数据的办法即可开展各种查询。
只是这种方式尽管会见引入一个问题,就是事情逻辑会渗透及应用层中失,并冒出大量还。比如,在实业中我们一般下IsActiveIsDeleted属性来代表软删除,而如实体中的某条数据给去除,那么UI中基本无见面另行显示就长达数据,那对实体的询问都亟需包含类似Where(c=> c.IsActive)的linq表达式。对于这种题材,我们尽好以存储中之点子吃,比如List()或者ListActive()开默认处理,而不是以应用服务层每次去指定询问条件。
而是实际是回来
IQueryable还是IEnumerable每个人的意见不同,具体但参考Repository 返回
IQueryable?还是
IEnumerable?。

4.3. IQueryable Vs IEnumerable

以概念仓储方法的返值经常,我们或会见比较疑惑,是应当直接回数据(IEnumerable)还是回查询(IQueryable)以便进行更的细化查询?返回IEnumerable会比较安全,但IQueryable提供了再也好之油滑。事实上,如果使用IQueryable作为返回值,我们仅仅提供平等种植读取数据的道即可进行各种查询。
可这种办法就是见面引入一个题材,就是业务逻辑会渗透及应用层中错过,并起大量重复。比如,在实体中我们一般用IsActiveIsDeleted性来代表软删除,而要实体中的某条数据被删去,那么UI中着力未会见更显示就漫漫数,那对于实体的询问都急需包含类似Where(c=> c.IsActive)的linq表达式。对于这种问题,我们无限好当储存中的计中,比如List()或者ListActive()举行默认处理,而无是于应用服务层每次去指定询问条件。
可是现实是返
IQueryable还是IEnumerable每个人之眼光不一,具体但参看Repository 返回
IQueryable?还是
IEnumerable?。

5. 事务管理和办事单元

物管理主要是应用服务层的关注点。然而,因为仓储及物管理紧密有关的。仓储就关注单一聚合的田间管理,而一个作业用例可能会见波及到强底集结。

东西管理由UOW(Unit of
Work)处理。UOW模式的打算是以事情用例的操作着跟踪聚合的装有改变。一旦闹了改动,UOW就动工作来协调持久化存储。为了保数据的完整性,如果提交数据失败,则会回滚所有变更,以确保数据保持中状态。

苟关于UOW又是一个犬牙交错的话题,我们继续又张嘴。

5. 事务管理和做事单元

事务管理主要是应用服务层的关注点。然而,因为仓储和事务管理紧密有关的。仓储就关心单一聚合的军事管制,而一个政工用例可能会见涉嫌到多的会师。

事务管理由UOW(Unit of
Work)处理。UOW模式的意是在作业用例的操作着跟踪聚合的富有改变。一旦出了改,UOW就以工作来协调持久化存储。为了保险数量的完整性,如果提交数据失败,则会回滚所有改变,以担保数据保持中状态。

若关于UOW又是一个繁杂的话题,我们继承还谈。

6. 仓储的倒模式(注意事项)

  1. 毫不支持即查询(ad hoc query)
    囤不该开放扩展,不要为支持多种形式的查询,定义比较泛的询问办法,它不但不克强烈发表仓储查询的来意,更可能会见招查询性能。
  2. 推迟加载是千篇一律种设计臭味
    汇应围绕不变性构建,并含有有必要的习性去支持不变性。
    因此,当加载聚合时,要么加载所有,要么一个为非加载。
    如果你有一个关系数据库并且在使用ORM作为数据模型,那么你或许能够延缓加载一些领域对象属性,这样就可以推加载不欲的聚合部分。但是,这样做的题材是,如果你不得不部分加载聚合,可能会见造成您的聚集边界错误。

  3. 甭采用聚合来贯彻报表需求
    表可能会见提到到差不多个档次的聚众,而仓储是拍卖单一聚合的。另外仓储是基于事务之,可能会见促成报表的特性问题。

  4. 总结

  5. 存储当作世界模型和数据模型的中介,它当映射领域模型到持久化存储。

  6. 囤实现了晶莹剔透持久化,即世界层不需要关爱世界对象如何持久化。
  7. 积存是一个契约,而无是数据访问层。它明确标明聚合所不可或缺的数额操作。
  8. ORM框架不是储存。仓储是同等种植架构模式。ORM用来因面向对象的方来代表数据模型。仓储使用ORM来协调领域模型和数据模型。
  9. 积存适用于有丰富领域模型的边界上下文。对于从未复杂工作逻辑的简限界上下文,直接采用持久化框架即可。
  10. 采用UOW进行事务管理。UOW负责跟踪对象的状态,仓储以UOW协调的事体中进行实际的持久化工作。
  11. 存储用于管理单个聚合,它不应当控制工作。

参考资料:
天地让设计(DDD)的实践经验分享的持久化透明
Repository Pattern–A data persistence
abstraction
领域让设计(DDD)的实践经验分享的ORM的思

6. 囤的倒模式(注意事项)

  1. 无须支持即查询(ad hoc query)
    储存不应该开放扩展,不要为支持多种形式的查询,定义比较常见的询问方式,它不只不能够明白表达仓储查询的意向,更可能会见导致查询性能。

  2. 延加载是平种植设计臭味
    集合应围绕不变性构建,并包含有必要的属性去支持不变性。
    因此,当加载聚合时,要么加载所有,要么一个乎非加载。
    如果你发出一个关系数据库并且正在使ORM作为数据模型,那么您可能能够延缓加载一些世界对象属性,这样即便好缓加载不需的汇聚部分。但是,这样做的问题是,如果您不得不部分加载聚合,可能会见招致您的集边界错误。

  3. 永不动聚合来促成报表需求
    表可能会见波及到大半只类别的集纳,而仓储是拍卖单一聚合的。另外仓储是因事务的,可能会见造成报表的属性问题。

  4. 总结

  5. 积存看作世界模型与数据模型的中介,它当映射领域模型到持久化存储。

  6. 存储实现了晶莹剔透持久化,即世界层不欲关爱世界对象如何持久化。
  7. 囤是一个契约,而未是数据访问层。它不言而喻标明聚合所必备的数据操作。
  8. ORM框架不是储存。仓储是同一种植架构模式。ORM用来以面向对象的方式来代表数据模型。仓储使用ORM来协调领域模型与数据模型。
  9. 仓储适用于具有丰富领域模型的界线上下文。对于没复杂工作逻辑的简要限界上下文,直接用持久化框架即可。
  10. 使用UOW进行事务管理。UOW负责跟踪对象的状态,仓储于UOW协调的业务中开展实际的持久化工作。
  11. 囤用于管理单个聚合,它不应控制作业。

参考资料:
世界让设计(DDD)的实践经验分享的持久化透明
Repository Pattern–A data persistence
abstraction
天地让设计(DDD)的实践经验分享的ORM的思维

相关文章