Domain repositories
Overview
The domain centric architecture is focused to business logic which can use db-platform independent domain repository pattern. Domain repository interfaces are typically used in command and query handlers and domain services.
Usage
There are several variants how to use repository in your domain, see DbRepositories for more details about registration of repositories for dependency injection.
//implicit usage for default context in command/query handler
private readonly IMyExampleRepository _myExampleRepository;
private readonly IMyExampleReadOnlyRepository _myExampleRepository;
var myExampleQuery = _myExampleRepository.GetAll();
//explicit usage for tenant context in command/query handler
private readonly ITenantDbScope<IMyExampleRepository> _myExampleRepositoryAccessor;
private readonly ITenantDbScope<IMyExampleReadOnlyRepository> _myExampleRepositoryAccessor;
var myExampleRepository = _myExampleRepositoryAccessor.Instance;
var myExampleQuery = myExampleRepository.GetAll();
//explicit usage for master context
private readonly IMasterDbScope<IMyExampleRepository> _myExampleRepositoryAccessor;
private readonly IMasterDbScope<IMyExampleReadOnlyRepository> _myExampleRepositoryAccessor;
var myExampleRepository = _myExampleRepositoryAccessor.Instance;
var myExampleQuery = myExampleRepository.GetAll();
//hybrid usage for tenant and master context
private readonly IDbScopeSelector<IMyExampleRepository> _myExampleRepositorySelector;
private readonly IDbScopeSelector<IMyExampleReadOnlyRepository> _myExampleRepositorySelector;
var myExampleRepository = _myExampleRepositorySelector.GetRepository(accessLevel == DataAccessLevel.Public);
var myExampleQuery = myExampleRepository.GetAll();
Querying data
Example how to retrieve data filtered by base-entity and owned organizations filter using IQueryable<T> interface.
See DomainHelpers for ApplyPagingFilter method.
using ASOL.Core.Domain;
var myExampleQuery = _myExampleRepository
.Get(x => x.ParentId == null)
.ApplyBaseEntityFilter(query.BaseEntityFilter)
.ApplyOrganizationFilter(RuntimeContext.Security.Organizations);
var totalCount = myExampleQuery.Count();
var myExamples = myExampleQuery
.ApplyPagingFilter(query.PagingFilter)
.OrderByDescending(x => x.CreatedOn)
.ToList();
var result = new CollectionResult<MyExample> { Items = myExamples, TotalCount = totalCount };
Repository domain extensions
The repository domain extensions are the easy way to write reusable and persistence independent code for manipulation with data.
It is also useful to make fluent api extension methods decorating e.g. IQueryable<T> interface.
using ASOL.Core.Domain;
using ASOL.Core.Domain.Contracts;
namespace My.App.Domain.Repositories
{
public static class MyExampleRepositoryAndQueryableExtensions
{
/// <summary>
/// Get MyExamples filtered by navigationPath.
/// </summary>
public static IQueryable<MyExample> ApplyNavigationPathFilter(this IQueryable<MyExample> query, string navigationPath)
{
return query.Where(item => item.NavigationPath.ToLowerInvariant() == navigationPath.ToLowerInvariant());
}
/// <summary>
/// Get MyExamples by navigationPath.
/// </summary>
public static IQueryable<MyExample> GetByNavigationPath(this IMyExampleReadOnlyRepository repository, string applicationCode, string navigationPath, BaseEntityFilter entityFilter, string organizationId, bool excludeInternal)
{
var query = repository
.Get(item => item.ApplicationCode == applicationCode)
.ApplyNavigationPathFilter(navigationPath)
.ApplyBaseEntityFilter(entityFilter);
if (organizationId != null)
{
query = query.Where(item => item.OrganizationId == null || item.OrganizationId == organizationId);
}
if (excludeInternal)
{
query = query.Where(item => !item.IsInternal);
}
return query;
}
/// <summary>
/// Get MyExample by code.
/// </summary>
public static MyExample GetByCode(this IMyExampleReadOnlyRepository repository, string applicationCode, string code, BaseEntityFilter entityFilter, string organizationId, bool excludeInternal)
{
var query = repository
.Get(item => item.ApplicationCode == applicationCode && item.Code == code)
.ApplyBaseEntityFilter(entityFilter);
if (organizationId != null)
{
query = query.Where(item => item.OrganizationId == null || item.OrganizationId == organizationId);
}
if (excludeInternal)
{
query = query.Where(item => !item.IsInternal);
}
return query.FirstOrDefault();
}
/// <summary>
/// Get MyExamples by top parentId.
/// </summary>
public static IQueryable<MyExample> GetByTopParentIdAsync(this IMyExampleReadOnlyRepository repository, string applicationCode, string topParentId, BaseEntityFilter entityFilter, string organizationId, bool excludeInternal)
{
var query = repository
.Get(item => item.ApplicationCode == applicationCode && item.TopParentId == topParentId)
.ApplyBaseEntityFilter(entityFilter);
if (organizationId != null)
{
query = query.Where(item => item.OrganizationId == null || item.OrganizationId == organizationId);
}
if (excludeInternal)
{
query = query.Where(item => !item.IsInternal);
}
return query;
}
}
}