问题
In ASP.NET Boilerplate, there are built-in Data Filters like Tenant filter, and we could use SetTenantId
to enable querying specific tenantId
.
As per the official document, it did not support custom Filter
in EF Core, unlike EF 6.x.
I am wondering how to achieve a similar filter for OrganizationUnitId
parameter.
This is what I have done so far:
Override
CreateFilterExpression
:protected override Expression<Func<TEntity, bool>> CreateFilterExpression<TEntity>() { Expression<Func<TEntity, bool>> expression = null; if (typeof(IMayHaveOrganizationUnit).IsAssignableFrom(typeof(TEntity))) { Expression<Func<TEntity, bool>> mayHaveOUFilter = e => ((IMayHaveOrganizationUnit)e).OrganizationUnitId == CurrentOrganizationUnitId || (((IMayHaveOrganizationUnit)e).OrganizationUnitId == CurrentOrganizationUnitId) == IsMayHaveOrganizationUnitFilterEnabled; expression = expression == null ? mayHaveOUFilter : CombineExpressions(expression, mayHaveOUFilter); } expression = expression == null ? base.CreateFilterExpression<TEntity>() : CombineExpressions(expression, base.CreateFilterExpression<TEntity>()); return expression; }
I register the new filter by code below:
Configuration.UnitOfWork.RegisterFilter("MayHaveOrganizationUnit", true);
But, how can I implement the code to set OrganizationUnitId
?
SetTenantId
is used to configure the tenantId
, how could I configure OrganizationUnitId
from UnitOfWork
?
I try to inherit
ClaimsAbpSession
like below:public class CustomAbpSession : ClaimsAbpSession, ICustomAbpSession { private readonly IRepository<User, long> _userRepository; public CustomAbpSession( IRepository<User, long> userRepository, IPrincipalAccessor principalAccessor, IMultiTenancyConfig multiTenancy, ITenantResolver tenantResolver, IAmbientScopeProvider<SessionOverride> sessionOverrideScopeProvider) : base(principalAccessor, multiTenancy, tenantResolver, sessionOverrideScopeProvider) { _userRepository = userRepository; } public virtual long? OrganizationUnitId { get { if (UserId != null) { var user = _userRepository.Get(UserId.Value); return 1; } return null; } } public long? ImpersonatorOrganizationUnitId => throw new NotImplementedException(); }
protected virtual long? GetCurrentOrganizationUnitIdOrNull() { return 3; // ((ICustomAbpSession)AbpSession).OrganizationUnitId; }
Use code below to register custom
IAbpSession
:Configuration.ReplaceService(typeof(IAbpSession), () => { IocManager.Register<IAbpSession, CustomAbpSession>(DependencyLifeStyle.Transient); });
Usage:
public List<Product> GetAll()
{
using (CurrentUnitOfWork.SetFilterParameter("MayHaveOrganizationUnit", "OrganizationUnitId", 2))
{
return _productRepositry.GetAll().ToList();
}
}
But, it always return value from OrganizationUnitId
in CustomAbpSession
, this method CurrentUnitOfWork.SetFilterParameter
did not set the value into filter.
回答1:
This isn't just a few lines of code.
Start with how IMayHaveTenant
is filtered in CreateFilterExpression.
You can override ShouldFilterEntity and CreateFilterExpression
in your DbContext
.
SetTenantId
is used to configure the tenantId, how could I configureOrganizationUnitId
fromUnitOfWork
?
You can use the equivalent SetFilterParameter method.
But, it always return value from
OrganizationUnitId
inCustomAbpSession
, this methodCurrentUnitOfWork.SetFilterParameter
did not set the value into filter.
From CurrentUnitOfWorkProvider.Current
, you can access Filters:
protected virtual long? GetCurrentOrganizationUnitIdOrNull()
{
if (CurrentUnitOfWorkProvider != null &&
CurrentUnitOfWorkProvider.Current != null)
{
return CurrentUnitOfWorkProvider.Current
.Filters.FirstOrDefault(f => f.FilterName == "MayHaveOrganizationUnit")?
.FilterParameters["OrganizationUnitId"] as long?;
}
return ((ICustomAbpSession)AbpSession).OrganizationUnitId;
}
来源:https://stackoverflow.com/questions/49956072/implement-organizationunit-filter-in-asp-net-core