使用Apworks开发基于CQRS架构的应用程序(三):创设快照

由于事件起点(伊芙(Eve)nt
Sourcing)的需,领域事件需要为保留及表面的贮存系统中。由于事件本身描述了当特定目的及所生的事务,因而,为了可以跟对象状态的浮动历程为博取伊芙(Eve)nt
Audit的力,我们总是拿事件之数据保存于蕴藏系统面临,而平昔不去删除其。或许你会以为,那样做小极端,时间增长了,存储系统受到的数据量将移得要命巨大。碰到这种情景,你待引入备份和归档策略,而不是直接用过期的多寡删除,因为,存储成本是方便的,但数额也是暴发价的。

于片生命周期相比丰硕的世界对象而言,发生在它们身上的事件数量会趁时间的推迟而增大,甚至会变换得巨大。于是,通过下这汪洋的轩然大波数量来重建领域模型将转移得特别耗时。由此,我们要引入“快照”的概念。当世界对象知足一个特定的准绳时(快照策略),系统便会面吧底老成一个“快照”。比如,系统架构师能够安装:当有n个事件有在某某圈子对象上时时,将晤面也夫目的来“快照”。下次当系统要重建这些目的时,只待由“快照”存储着拿走目前一样不善的快照数据,通过快照数据来对象,进而再相继个地以有在“快照”之后的风波逐个地“重现”在斯目的上,于是,对象就可吃急迅地东山再起到结尾一个事件闹时的状态。

就Apworks框架而言,当前所支撑的快照策略分外简单。它由Apworks.伊芙(Eve)nts.Storage.IDomain伊芙(Eve)ntStorage.CanCreateOrUpdateSnapshot方法定义,而Apworks.伊夫nts.Storage.SqlDomain伊芙ntStorage类则就此这么同样栽快照策略实现了此接口:每当第1000只事件有常,系统就相会为相应的世界对象做一样蹩脚快照。由此,假若你打算在你的应用程序中延续以SQL
Server作为事件起源的积存系统,并且打算定义自己的快照策略的话,你可以创建一个继续给Apworks.伊夫(Eve)nts.Storage.SqlDomain伊芙(Eve)ntStorage的类,并再度写CanCreateOrUpdateSnapshot方法。假诺您打算接纳外的存储系统(比如MySQL,Oracle,NoSQL方案要内存数据库等),那么您虽然待创制一个实现Apworks.伊夫nts.Storage.IDomain伊夫(Eve)ntStorage接口的接近,然后实现CanCreateOrUpdateSnapshot方法。

前天深受大家回去到TinyLibraryCQRS解决方案,在面前的段中,我们创造了点滴单聚合根:Reader和Book,在及时简单只聚合根里,有些许独无实现的道。现在我们来实现这半个道以便让大家的应用程序辅助快照功效。

  1. 右键单击TinyLibrary.Domain项目,单击 Add | New Folder
    菜单,将 New Folder 重命名吧 Snapshots
  2. 用底的办法创设一个BookSnapshot

       1: using System;
    
       2: using Apworks.Snapshots;
    
       3:  
    
       4: namespace TinyLibrary.Domain.Snapshots
    
       5: {
    
       6:     [Serializable]
    
       7:     public class BookSnapshot : Snapshot
    
       8:     {
    
       9:         public string Title { get; set; }
    
      10:         public string Publisher { get; set; }
    
      11:         public DateTime PubDate { get; set; }
    
      12:         public string ISBN { get; set; }
    
      13:         public int Pages { get; set; }
    
      14:         public bool Lent { get; set; }
    
      15:     }
    
      16: }
    
注意我们使用System.SerializableAttribute特性标注了上面的类,因为我们需要将快照数据保存到存储系统中。你也会注意到,这个类的结构跟Book实体的结构很像,这是因为快照本身的作用就是反映并存储与之对应的实体在某个时间点的状态。
  1. 同理,添加ReaderSnapshot

       1: using System;
    
       2: using System.Collections.Generic;
    
       3: using Apworks.Snapshots;
    
       4:  
    
       5: namespace TinyLibrary.Domain.Snapshots
    
       6: {
    
       7:     [Serializable]
    
       8:     public class ReaderSnapshot : Snapshot
    
       9:     {
    
      10:         public string LoginName { get; set; }
    
      11:         public string Name { get; set; }
    
      12:  
    
      13:         public List<BookSnapshot> Books { get; set; }
    
      14:     }
    
      15: }
    
  2. 回到Book看似,用底的主意实现DoBuildFromSnapshotDoCreateSnapshot方法

       1: protected override void DoBuildFromSnapshot(ISnapshot snapshot)
    
       2: {
    
       3:     BookSnapshot bs = (BookSnapshot)snapshot;
    
       4:     this.Title = bs.Title;
    
       5:     this.Publisher = bs.Publisher;
    
       6:     this.PubDate = bs.PubDate;
    
       7:     this.ISBN = bs.ISBN;
    
       8:     this.Pages = bs.Pages;
    
       9:     this.Lent = bs.Lent;
    
      10: }
    
      11:  
    
      12: protected override ISnapshot DoCreateSnapshot()
    
      13: {
    
      14:     BookSnapshot bs = new BookSnapshot();
    
      15:     bs.ISBN = this.ISBN;
    
      16:     bs.Lent = this.Lent;
    
      17:     bs.Pages = this.Pages;
    
      18:     bs.PubDate = this.PubDate;
    
      19:     bs.Publisher = this.Publisher;
    
      20:     bs.Title = this.Title;
    
      21:     return bs;
    
      22: }
    
  3. 回到Reader仿佛,用底的章程贯彻DoBuildFromSnapshotNoSQL,和DoCreateSnapshot方法

       1: protected override void DoBuildFromSnapshot(ISnapshot snapshot)
    
       2: {
    
       3:     ReaderSnapshot rs = (ReaderSnapshot)snapshot;
    
       4:     this.Books.Clear();
    
       5:     foreach (var bk in rs.Books)
    
       6:     {
    
       7:         this.Books.Add(Book.Create(bk.AggregateRootId, 
    
       8:             bk.Title, 
    
       9:             bk.Publisher, 
    
      10:             bk.PubDate, 
    
      11:             bk.ISBN, 
    
      12:             bk.Pages, 
    
      13:             bk.Lent));
    
      14:     }
    
      15:     this.LoginName = rs.LoginName;
    
      16:     this.Name = rs.Name;
    
      17: }
    
      18:  
    
      19: protected override ISnapshot DoCreateSnapshot()
    
      20: {
    
      21:     ReaderSnapshot rs = new ReaderSnapshot();
    
      22:     rs.Books = new List<BookSnapshot>();
    
      23:     foreach (var bk in this.Books)
    
      24:     {
    
      25:         rs.Books.Add((BookSnapshot)bk.CreateSnapshot());
    
      26:     }
    
      27:     rs.LoginName = this.LoginName;
    
      28:     rs.Name = this.Name;
    
      29:     return rs;
    
      30: }
    
  4. 以完成了方的享有手续后,我们的ReaderBook看似定义如下:

       1: using System;
    
       2: using Apworks;
    
       3: using Apworks.Snapshots;
    
       4:  
    
       5: namespace TinyLibrary.Domain
    
       6: {
    
       7:     public class Book : SourcedAggregateRoot
    
       8:     {
    
       9:         public string Title { get; private set; }
    
      10:         public string Publisher { get; private set; }
    
      11:         public DateTime PubDate { get; private set; }
    
      12:         public string ISBN { get; private set; }
    
      13:         public int Pages { get; private set; }
    
      14:         public bool Lent { get; private set; }
    
      15:  
    
      16:         public Book() : base() {  }
    
      17:         public Book(long id) : base(id) {  }
    
      18:  
    
      19:         protected override void DoBuildFromSnapshot(ISnapshot snapshot)
    
      20:         {
    
      21:             BookSnapshot bs = (BookSnapshot)snapshot;
    
      22:             this.Title = bs.Title;
    
      23:             this.Publisher = bs.Publisher;
    
      24:             this.PubDate = bs.PubDate;
    
      25:             this.ISBN = bs.ISBN;
    
      26:             this.Pages = bs.Pages;
    
      27:             this.Lent = bs.Lent;
    
      28:         }
    
      29:  
    
      30:         protected override ISnapshot DoCreateSnapshot()
    
      31:         {
    
      32:             BookSnapshot bs = new BookSnapshot();
    
      33:             bs.ISBN = this.ISBN;
    
      34:             bs.Lent = this.Lent;
    
      35:             bs.Pages = this.Pages;
    
      36:             bs.PubDate = this.PubDate;
    
      37:             bs.Publisher = this.Publisher;
    
      38:             bs.Title = this.Title;
    
      39:             return bs;
    
      40:         }
    
      41:     }
    
      42:  
    
      43:     public class Reader : SourcedAggregateRoot
    
      44:     {
    
      45:         public string LoginName { get; private set; }
    
      46:         public string Name { get; private set; }
    
      47:         public List<Book> Books { get; private set; }
    
      48:  
    
      49:         public Reader() : base() { Books = new List<Book>(); }
    
      50:         public Reader(long id) : base(id) { Books = new List<Book>(); }
    
      51:  
    
      52:         protected override void DoBuildFromSnapshot(ISnapshot snapshot)
    
      53:         {
    
      54:             ReaderSnapshot rs = (ReaderSnapshot)snapshot;
    
      55:             this.Books.Clear();
    
      56:             foreach (var bk in rs.Books)
    
      57:             {
    
      58:                  this.Books.Add(Book.Create(bk.AggregateRootId, 
    
      59:                     bk.Title, 
    
      60:                     bk.Publisher, 
    
      61:                     bk.PubDate, 
    
      62:                     bk.ISBN, 
    
      63:                     bk.Pages, 
    
      64:                     bk.Lent));
    
      65:             }
    
      66:             this.LoginName = rs.LoginName;
    
      67:             this.Name = rs.Name;
    
      68:         }
    
      69:  
    
      70:         protected override ISnapshot DoCreateSnapshot()
    
      71:         {
    
      72:             ReaderSnapshot rs = new ReaderSnapshot();
    
      73:             rs.Books = new List<BookSnapshot>();
    
      74:             foreach (var bk in this.Books)
    
      75:             {
    
      76:                 rs.Books.Add((BookSnapshot)bk.CreateSnapshot());
    
      77:             }
    
      78:             rs.LoginName = this.LoginName;
    
      79:             rs.Name = this.Name;
    
      80:             return rs;
    
      81:         }
    
      82:     }
    
      83: }
    

当产一样篇稿子中,我们拿引入世界事件,并逐渐向目的吃投入世界逻辑。

网站地图xml地图