使用实体框架(EF)在存储库中对聚合的实体进行分页

3
假设我有以下聚合根:
public class Aggregate
{
    public int Id {get; set;}

    public List<Entity> Entities {get; set;}
}

以下是相关仓库:

public class AggregateRepository
{
   public Aggregate GetPaged(int Id)
   {
     return db.Aggregate
              .Include(x=>x.Entities)
              .Find(id)             
   }
}
问题:如何获取分页和排序的实体列表?获取分页和排序的实体的最佳方法是什么,同时还包括聚合信息? 编辑: 您认为以下方法怎么样?
public class AggregateRepository
    {
       public IEnumerable<Entity> GetEntitiesPaged(int id)
       {
         return db.Aggregate
                  .Include(x=>x.Aggregate)
                  .Where(x=>x.Id = id)
                  .Select(x=>x.Entities)
                  .Take(20);        
       }
    }

我可以接收包含聚合对象的实体列表(在本例中有20个实体),而不是返回一个聚合对象。这是在DDD模式中使用聚合的好方法吗?


为了给您一个有用的答案,我想知道您使用分页和排序实体列表的目的是什么。
  • 您是否需要在写入或读取模型中使用分页和排序的实体列表?
  • 您是否将使用此页面向用户展示实体?
  • 您是否将逐页阅读(查询)实体以强制执行域中的某些不变量?
- Ilya Palkin
2个回答

3
短回答是,应避免查询您的领域模型。最好使用专用的查询层并配合读取模型;否则使用类似于 DataRow 的更原始的东西。
更新:在查询时要尽量避免创建聚合根。这意味着不能访问存储库。查询层应该像这样:
public interface ISomethingQuery
{
    IEnumerable<SomethingDto> GetPage(SearchSPecification specification, int pageNumber);
    // -or-
    IEnumerable<DataRow> GetPage(SearchSPecification specification, int pageNumber);
}

您将使用此查询接口的实现来获取所需的显示/报告数据。

1
谢谢你的回答 :) 当你说:“使用具有读模型的专用查询层”时,是指在获取所有数据到内存中之后(调用GetPaged()方法后)这样做,对吗?这样,如果我的实体有很多数据,性能会降低,我想避免这种情况。 DataRow选项现在不是一个选择,因为我将不得不改变应用程序的方法,我不想这样做。 我编辑了我的帖子。 如果您想评论,我会感激。 - ASantos
我已经更新了答案,以更好地阐明这个问题 :) - Eben Roux

2
首先,您应该将写入端(命令)与读取端(查询)分开,这被称为CQRS。您可以查看此示例
但是,如果您只想获取分页和排序后的实体列表,则可以使用以下方法。
public ICollection<Aggregate> GetSortedAggregates(AggregateListFilter filter, out int rowCount)
{
    var query = (base.Repository.CurrentSession() as ISession).QueryOver<Aggregate>();

    query = query.And(q => q.Status != StatusType.Deleted);

    if (!string.IsNullOrWhiteSpace(filter.Name))
        query = query.And(q => q.Name == filter.Name);

    rowCount = query.RowCount();

    switch (filter.OrderColumnName)
    {
        case ".Name":
            query = filter.OrderDirection == OrderByDirections.Ascending ? query.OrderBy(x => x.Name).Asc : query.OrderBy(x => x.Name).Desc;
            break;
        default:
            query = filter.OrderDirection == OrderByDirections.Ascending ? query.OrderBy(x => x.Id).Asc : query.OrderBy(x => x.Id).Desc;
            break;
    }

    if (filter.CurrentPageIndex > 0)
    {
        return query
        .Skip((filter.CurrentPageIndex - 1) * filter.PageSize)
        .Take(filter.PageSize)
        .List();
    }

    return query.List();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接