<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      實現領域驅動設計 - 使用ABP框架 - 存儲庫

      存儲庫

      Repository 是一個類似于集合的接口,領域層和應用程序層使用它來訪問數據持久性系統(數據庫),以讀寫業務對象(通常是聚合)

      常見的存儲庫原則是:

      • 在領域層定義一個存儲庫接口(因為它被用于領域層和應用層),在基礎設施層實現(啟動模板中的EntityFrameworkCore項目)
      • 不要在存儲庫中包含業務邏輯。
      • 存儲庫接口應該是獨立于數據庫提供者/ ORM的。例如,不要從存儲庫方法返回DbSet。DbSet是 EF Core 提供的一個對象
      • 為聚合根創建存儲庫,而不是為所有實體。因為,子集合實體(聚合的)應該通過聚合根訪問

      不要在存儲庫中包含領域邏輯

      雖然這個規則在一開始看起來很明顯,但是很容易將業務邏輯泄露到存儲庫中

      示例:從存儲庫中獲取不活躍的問題

      public interface IIssueRepository : IRepository<Issue, Guid>
      {
          Task<List<Issue>> GetInActiveIssuesAsync();
      }
      

      IIssueRepository 擴展了標準 IRepository<...> 接口,添加GetInActiveIssuesAsync 方法。這個存儲庫使用這樣一個Issue類:

      public class Issue : AggregateRoot<Guid>, IHasCreationTime
      {
          public bool IsClosed { get; private set; }
          public Guid? AssignedUserId { get; private set; }
          public DateTime CreationTime { get; private set; }
          public DateTime? LastCommentTime { get; private set; }
      }
      

      (代碼只顯示了本例所需的屬性)

      規則規定存儲庫不應該知道業務規則。這里的問題是 “什么是不活躍的問題? ”它是業務規則定義嗎?”

      讓我們看看實現來理解它:

      public class EfCoreIssueRepository : 
          EfCoreRepository<IssueTrackingDbContext, Issue, Guid>
          IIssueRepository
      {
          public async Task<List<Issue>> GetInActiveIssuesAsync()
          {
              var daysAgo30 = DateTime.Now.Subtract(TimeSpan.FromDays(30));
              var dbSet = await GetDbSetAsync();
              return await dbSet.Where(i => 
                  //開放的
                  !i.IsClosed &&
      
                  //沒有分配給任何人
                  i.AssignedUserId == null &&
      
                  //30天前創建的
                  i.CreationTime < daysAgo30 &&
      
                  //最近30天內沒有任何評論
                  (i.LastCommentTime == null || i.LastCommentTime < daysAgo30)
                  
                  ).ToListAsync();
          }
      }
      

      (使用EF Core實現。查看 EF Core集成文檔,了解如何使用 EF Core 創建自定義存儲庫。)

      當我們檢查 GetInActiveIssuesAsync 的實現時,我們看到了一個業務規則,它給出了不活躍的問題的定義:該問題應該是開放的,沒有分配給任何人,30天前創建的,并且在最近30天內沒有任何評論

      這是隱藏在存儲庫方法中的業務規則的隱式定義。當我們需要重用該業務邏輯時,就會出現問題

      例如,假設我們想要在 Issue 實體上添加一個 bool IsInActive() 方法。這樣,當我們有 Issue 實體時,我們就可以檢查活躍度。

      讓我們看看實現:

      public class Issue : AggregateRoot<Guid>, IHasCreationTime
      {
          public bool IsClosed { get; private set; }
          public Guid? AssignedUserId { get; private set; }
          public DateTime CreationTime { get; private set; }
          public DateTime? LastCommentTime { get; private set; }
      
          public bool IsInActive()
          {
              var daysAgo30 = DateTime.Now.Subtract(TimeSpan.FromDays(30));
              return 
                  //開放的
                  !IsClosed &&
      
                  //沒有分配給任何人
                  AssignedUserId == null &&
      
                  //30天前創建的
                  CreationTime < daysAgo30 &&
      
                  //最近30天內沒有任何評論
                  (LastCommentTime == null || LastCommentTime < daysAgo30);
          }
      }
      

      我們必須復制/粘貼/修改代碼。如果活動性的定義改變了呢?我們不應該忘記更新這兩個地方。這是業務邏輯的重復,這是非常危險的

      這個問題的一個很好的解決方案是規范模式!

      規范

      規范是一個命名的、可重用的、可組合的和可測試的類,用于基于業務規則篩選領域對象

      ABP框架提供了必要的基礎設施來輕松地創建規范類并在應用程序代碼中使用它們。讓我們將不活躍的問題過濾器實現為一個規范類:

      public class InActiveIssueSpecification : Specification<Issue>
      {
          public override Expression<Func<Issue,bool>> ToExpression()
          {
              var daysAgo30 = DateTime.Now.Subtract(TimeSpan.FromDays(30));
              return i =>
                  //開放的
                  !i.IsClosed &&
      
                  //沒有分配給任何人
                  i.AssignedUserId == null &&
      
                  //30天前創建的
                  i.CreationTime < daysAgo30 &&
      
                  //最近30天內沒有任何評論
                  (i.LastCommentTime == null || i.LastCommentTime < daysAgo30);
          }
      }
      

      Specification<T> 基類通過定義表達式簡化了創建規范類的工作。只是將表達式從存儲庫移到這里
      現在我們就可以在 Issue 實體和 EfCoreIssueRepository 類中復用 InActiveIssueSpecification 了

      在實體中使用規范

      Specification 類提供了一個 IsSatisfiedBy 方法,如果給定的對象(實體)滿足規范,該方法返回true。我們可以重寫這個 Issue。IsInActive 方法如下所示:

      public class Issue : AggregateRoot<Guid>, IHasCreationTime
      {
          public bool IsInActive()
          {
             return new InActiveIssueSpecification().IsSatisfiedBy(this);
          }
      }
      

      在存儲庫中使用規范

      首先,從存儲庫接口開始:

      public interface IIssueRepository : IRepository<Issue, Guid>
      {
          Task<List<Issue>> GetIssuesAsync(ISpecification<Issue> spec);
      }
      
      • 將 GetInActiveIssuesAsync 重命名為簡單的 GetIssuesAsync, 并接受一個規范對象
      • 由于規范(過濾器)已經從存儲庫中移出,我們不再需要創建不同的方法來獲得不同條件下的問題(比如: GetAssignedIssues(...) , GetLockedIssues(...) 等等)

      更新后的存儲庫實現可以像這樣:

      public class EfCoreIssueRepository : 
          EfCoreRepository<IssueTrackingDbContext, Issue, Guid>
          IIssueRepository
      {
          public async Task<List<Issue>> GetIssuesAsync(ISpecification<Issue> spec)
          {
              var dbSet = await GetDbSetAsync();
              return await dbSet
                  .Where(spec.ToExpression())
                  .ToListAsync();
          }
      }
      

      因為ToExpression()方法返回一個表達式,所以它可以直接傳遞給Where方法來過濾實體

      • 最終,我們做到了業務邏輯的代碼復用,消除了安全隱患

      使用默認的存儲庫

      實際上,您不必創建自定義存儲庫才能使用規范。標準的IRepository已經擴展了IQueryable,所以你可以在上面使用標準的LINQ擴展方法:

      public class IssueAppService : ApplicationService, IIssueAppService
      {
          public async Task<List<Issue>> GetInActiveIssuesAsync()
          {
              var queryable = await _issueRepository.GetQueryableAsync();
              var issues = await AsyncExecuter.ToListAsync(
                  queryable.Where(new InActiveIssueSpecification())
              );
          }
      }
      

      AsyncExecuter 是ABP框架提供的一個實用工具,用于使用異步LINQ擴展方法(如這里的ToListAsync),而不依賴于EF Core NuGet包。有關更多信息,請參閱 Repositories文檔

      組合規范

      規范的一個強大的方面是它們是可組合的。假設我們有另一個規范,它只在問題位于里程碑時返回true

      public class MilestoneSpecification : Specification<Issue>
      {
          public Guid MilestoneId { get; }
          public override Expression<Func<Issue,bool>> ToExpression()
          {
              return i => i.MilestoneId == MilestoneId;
          }
      }
      

      本規范是參數化的,與 InActiveIssueSpecification 有所不同。我們可以結合這兩個規范來獲得特定里程碑中的非活躍問題列表

      public class IssueAppService : ApplicationService, IIssueAppService
      {
          public async Task<List<Issue>> GetInActiveIssuesWithinMilestoneAsync(Guid milestoneId)
          {
              var queryable = await _issueRepository.GetQueryableAsync();
              var issues = await AsyncExecuter.ToListAsync(
                  queryable.Where(
                      new InActiveIssueSpecification()
                      .And(new MilestoneSpecification(milestoneId))
                      .ToExpression()
                  )
              );
          }
      }
      

      上面的示例使用And擴展方法來組合這些規范。還有更多的組合方法可用,比如 Or(…) 和 AndNot(…)

      有關ABP框架提供的規范基礎架構的更多細節,請參閱 規范文檔

      posted @ 2022-06-23 15:48  Broadm  閱讀(764)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 人人爽人人模人人人爽人人爱| 精精国产xxxx视频在线| 天堂网av一区二区三区| 久久中文字幕无码专区| 国产一区二区三区综合视频| 高潮潮喷奶水飞溅视频无码| 亚洲欧美牲交| 国产在线无码不卡播放| 中文字幕在线视频不卡| 国产成人一区二区三区在线| av性色av久久无码ai换脸| 激情综合网激情五月俺也想| 亚洲精品熟女一区二区| 亚洲一区二区偷拍精品| 国产 一区二区三区视频| 国产11一12周岁女毛片| 人妻在线中文字幕| 大肉大捧一进一出视频| 国产不卡在线一区二区| 无码人妻斩一区二区三区| 精品国产福利一区二区在线| 亚洲精品久久久蜜桃| 妺妺窝人体色www婷婷| 亚洲av激情一区二区| 亚洲一区二区精品极品| 亚洲国产精品久久久天堂麻豆宅男| 夜夜夜高潮夜夜爽夜夜爰爰| 天堂网在线观看| 男女xx00xx的视频免费观看| 人妻少妇乱子伦精品| 无码人妻丝袜在线视频| 欧美国产精品啪啪| 国产成人午夜福利在线播放| 亚洲av综合色一区二区| 猫咪www免费人成网站| 日韩一级伦理片一区二区| 中文字幕人妻在线精品| 精品人妻系列无码人妻漫画| 狠狠噜天天噜日日噜无码| 国产精品涩涩涩视频网站| 国产在线视频不卡一区二区|