在 ASP.NET Core 中实施 OrganizationUnit 过滤器
Implement OrganizationUnit filter in ASP.NET Core
在 ASP.NET 样板中,有内置的数据过滤器,如租户过滤器,我们可以使用 SetTenantId
来启用查询特定 tenantId
.
根据官方文档,它不支持 EF Core 中的自定义 Filter
,这与 EF 6.x 不同。
我想知道如何为 OrganizationUnitId
参数实现类似的过滤器。
这是我到目前为止所做的:
覆盖 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;
}
我通过下面的代码注册了新的过滤器:
Configuration.UnitOfWork.RegisterFilter("MayHaveOrganizationUnit", true);
但是,我该如何实现设置 OrganizationUnitId
的代码?
SetTenantId
用于配置tenantId
,我如何配置OrganizationUnitId
从UnitOfWork
?
我尝试继承 ClaimsAbpSession
如下所示:
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;
}
使用下面的代码注册自定义 IAbpSession
:
Configuration.ReplaceService(typeof(IAbpSession), () =>
{
IocManager.Register<IAbpSession, CustomAbpSession>(DependencyLifeStyle.Transient);
});
用法:
public List<Product> GetAll()
{
using (CurrentUnitOfWork.SetFilterParameter("MayHaveOrganizationUnit", "OrganizationUnitId", 2))
{
return _productRepositry.GetAll().ToList();
}
}
但是,CustomAbpSession
中 OrganizationUnitId
的值总是 return,此方法 CurrentUnitOfWork.SetFilterParameter
没有将值设置到过滤器中。
这不仅仅是几行代码。
从 IMayHaveTenant
在 CreateFilterExpression
中的过滤方式开始。
您可以在 DbContext
中覆盖 ShouldFilterEntity
和 CreateFilterExpression
。
SetTenantId
is used to configure the tenantId, how could I configure OrganizationUnitId
from UnitOfWork
?
您可以使用等效的 SetFilterParameter
方法。
But, it always return value from OrganizationUnitId
in CustomAbpSession
, this method CurrentUnitOfWork.SetFilterParameter
did not set the value into filter.
从 CurrentUnitOfWorkProvider.Current
,您可以访问 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;
}
在 ASP.NET 样板中,有内置的数据过滤器,如租户过滤器,我们可以使用 SetTenantId
来启用查询特定 tenantId
.
根据官方文档,它不支持 EF Core 中的自定义 Filter
,这与 EF 6.x 不同。
我想知道如何为 OrganizationUnitId
参数实现类似的过滤器。
这是我到目前为止所做的:
覆盖
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; }
我通过下面的代码注册了新的过滤器:
Configuration.UnitOfWork.RegisterFilter("MayHaveOrganizationUnit", true);
但是,我该如何实现设置 OrganizationUnitId
的代码?
SetTenantId
用于配置tenantId
,我如何配置OrganizationUnitId
从UnitOfWork
?
我尝试继承
ClaimsAbpSession
如下所示: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; }
使用下面的代码注册自定义
IAbpSession
:Configuration.ReplaceService(typeof(IAbpSession), () => { IocManager.Register<IAbpSession, CustomAbpSession>(DependencyLifeStyle.Transient); });
用法:
public List<Product> GetAll()
{
using (CurrentUnitOfWork.SetFilterParameter("MayHaveOrganizationUnit", "OrganizationUnitId", 2))
{
return _productRepositry.GetAll().ToList();
}
}
但是,CustomAbpSession
中 OrganizationUnitId
的值总是 return,此方法 CurrentUnitOfWork.SetFilterParameter
没有将值设置到过滤器中。
这不仅仅是几行代码。
从 IMayHaveTenant
在 CreateFilterExpression
中的过滤方式开始。
您可以在 DbContext
中覆盖 ShouldFilterEntity
和 CreateFilterExpression
。
SetTenantId
is used to configure the tenantId, how could I configureOrganizationUnitId
fromUnitOfWork
?
您可以使用等效的 SetFilterParameter
方法。
But, it always return value from
OrganizationUnitId
inCustomAbpSession
, this methodCurrentUnitOfWork.SetFilterParameter
did not set the value into filter.
从 CurrentUnitOfWorkProvider.Current
,您可以访问 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;
}