• 推荐领域层中定义仓储接口.
    • 推荐每个聚合根定义仓储接口(如 )并创建相应的实现.
      • 推荐 在应用代码中使用仓储时应该注入仓储接口.
      • 不推荐 在应用代码中使用泛型仓储接口(如 IRepository<IdentityUser, Guid>).
      • 不推荐 在应用代码(领域, 应用… 层)中使用 IQueryable<TEntity> 特性.
    1. public interface IIdentityUserRepository : IBasicRepository<IdentityUser, Guid>
    2. {
    3. //...
    4. }
    • 不推荐 仓储接口继承 IRepository<TEntity, TKey> 接口. 因为它继承了 IQueryable 而仓储不应该将IQueryable暴漏给应用.
    • 不推荐 为实体定义仓储接口,因为它们不是聚合根.
    • 推荐 所有的仓储方法定义为 异步.
    • 推荐 为仓储的每个方法添加 可选参数 cancellationToken . 例:
    • 推荐 为仓储的每个异步方法创建一个 同步扩展 方法. 示例:
    1. public static class IdentityUserRepositoryExtensions
    2. {
    3. public static IdentityUser FindByNormalizedUserName(
    4. this IIdentityUserRepository repository,
    5. [NotNull] string normalizedUserName)
    6. {
    7. return AsyncHelper.RunSync(
    8. () => repository.FindByNormalizedUserNameAsync(normalizedUserName)
    9. );
    10. }
    • 推荐 为仓储中返回单个实体的方法添加一个可选参数 bool includeDetails = true (默认值为true). 示例:
    • 推荐 为仓储中返回实体列表的方法添加一个可选参数 bool includeDetails = false (默认值为false). 示例:
    1. Task<List<IdentityUser>> GetListByNormalizedRoleNameAsync(
    2. string normalizedRoleName,
    3. bool includeDetails = false,
    4. CancellationToken cancellationToken = default
    5. );
    • 不推荐 创建复合类通过调用仓储单个方法返回组合实体. 比如: UserWithRoles, UserWithTokens, UserWithRolesAndTokens. 相反, 正确的使用 选项, 在需要时加载实体所有的详细信息.
    • 避免 为了从仓储中获取实体的部分属性而为实体创建投影类. 比如: 避免通过创建BasicUserView来选择所需的一些属性. 相反可以直接使用聚合根类. 不过这条规则有例外情况:
      • 性能对于用例来说非常重要,而且使用整个聚合根对性能的影响非常大.