使用 EF Core 自定义筛选器
Custom Filter with EF Core
我在这里找到了关于这个主题的几个答案,但它们没有完全涵盖我的问题。
我的目标是让实体拥有用户作为所有者。
我定义了一个接口 IMustHaveUser
public interface IMustHaveUser
{
long UserId { get; set; }
}
然后我在我的实体产品中实现它
我在预初始化方法中的 EFCoreModule 中注册自定义过滤器
public override void PreInitialize() {
//Register custom data filters
Configuration.UnitOfWork.RegisterFilter("MustHaveUser", true);
//other code here...
}
最后在 DBContext 中设置我的过滤器
定义一个 属性 检查过滤器是否已启用
protected virtual bool IsMustHaveUserFilterEnabled => CurrentUnitOfWorkProvider?.Current?.IsFilterEnabled("MustHaveUser") == true;
并覆盖 CreateFilterExpression 方法。
protected override Expression<Func<TEntity, bool>> CreateFilterExpression<TEntity>()
{
var expression = base.CreateFilterExpression<TEntity>();
if (typeof(IMustHaveUser).IsAssignableFrom(typeof(TEntity)))
{
Expression<Func<TEntity, bool>> userFilter = e => ((IMustHaveUser) e).UserId == AbpSession.UserId || (((IMustHaveUser) e).UserId == AbpSession.UserId) == IsMustHaveUserFilterEnabled;
expression = expression == null ? userFilter : CombineExpressions(expression, userFilter);
}
return expression;
}
现在,当我创建实体时,我必须手动设置 UserID。
基本上我用方法
在领域层写了 ProductManager
void Create(Product product, UserIdentity user){
product.UserId = user.UserId;
//Other business rules and insert with repository
}
我的问题是关于设置当前 UserId。还有其他最简单(更好)的方法吗?
我忘了DI。找到了解决方案。基本上我已经将 IAbpSession 注入 Automapper 配置文件并在那里映射 UserId。
public class AutoMapperProfile : AutoMapper.Profile
{
private IAbpSession _abpSession;
public AutoMapperProfile() {
_abpSession = IocManager.Instance.Resolve<IAbpSession>();
CreateMap<LicenseInput, License>()
.ForMember(x => x.UserId, options => options.MapFrom(src => _abpSession.UserId));
}
}
最终我采用了其他方式,因为这种方式使该代码难以进行集成测试。
我不知道为什么这一刻缺少文档,我不得不阅读 github 的源代码以了解现有过滤器的工作原理,例如 MustHaveTenant 等。
我在 AbpDbContext 中发现了名为 ApplyAbpConceptsForAddedEntity 的多态方法,它允许我实现它。
MyDbContext 中的最终代码如下所示:
protected override void ApplyAbpConceptsForAddedEntity(EntityEntry entry, long? userId, EntityChangeReport changeReport)
{
CheckAndSetMustHaveUserIdProperty(entry.Entity, userId);
base.ApplyAbpConceptsForAddedEntity(entry, userId, changeReport);
}
private void CheckAndSetMustHaveUserIdProperty(object entryEntity, long? userId)
{
if (userId == null)
return;
if (!(entryEntity is IMustHaveUser))
{
return;
}
var entity = entryEntity.As<IMustHaveUser>();
entity.UserId = userId.Value;
}
我在这里找到了关于这个主题的几个答案,但它们没有完全涵盖我的问题。 我的目标是让实体拥有用户作为所有者。 我定义了一个接口 IMustHaveUser
public interface IMustHaveUser
{
long UserId { get; set; }
}
然后我在我的实体产品中实现它
我在预初始化方法中的 EFCoreModule 中注册自定义过滤器
public override void PreInitialize() {
//Register custom data filters
Configuration.UnitOfWork.RegisterFilter("MustHaveUser", true);
//other code here...
}
最后在 DBContext 中设置我的过滤器 定义一个 属性 检查过滤器是否已启用
protected virtual bool IsMustHaveUserFilterEnabled => CurrentUnitOfWorkProvider?.Current?.IsFilterEnabled("MustHaveUser") == true;
并覆盖 CreateFilterExpression 方法。
protected override Expression<Func<TEntity, bool>> CreateFilterExpression<TEntity>()
{
var expression = base.CreateFilterExpression<TEntity>();
if (typeof(IMustHaveUser).IsAssignableFrom(typeof(TEntity)))
{
Expression<Func<TEntity, bool>> userFilter = e => ((IMustHaveUser) e).UserId == AbpSession.UserId || (((IMustHaveUser) e).UserId == AbpSession.UserId) == IsMustHaveUserFilterEnabled;
expression = expression == null ? userFilter : CombineExpressions(expression, userFilter);
}
return expression;
}
现在,当我创建实体时,我必须手动设置 UserID。 基本上我用方法
在领域层写了 ProductManagervoid Create(Product product, UserIdentity user){
product.UserId = user.UserId;
//Other business rules and insert with repository
}
我的问题是关于设置当前 UserId。还有其他最简单(更好)的方法吗?
我忘了DI。找到了解决方案。基本上我已经将 IAbpSession 注入 Automapper 配置文件并在那里映射 UserId。
public class AutoMapperProfile : AutoMapper.Profile
{
private IAbpSession _abpSession;
public AutoMapperProfile() {
_abpSession = IocManager.Instance.Resolve<IAbpSession>();
CreateMap<LicenseInput, License>()
.ForMember(x => x.UserId, options => options.MapFrom(src => _abpSession.UserId));
}
}
最终我采用了其他方式,因为这种方式使该代码难以进行集成测试。 我不知道为什么这一刻缺少文档,我不得不阅读 github 的源代码以了解现有过滤器的工作原理,例如 MustHaveTenant 等。 我在 AbpDbContext 中发现了名为 ApplyAbpConceptsForAddedEntity 的多态方法,它允许我实现它。
MyDbContext 中的最终代码如下所示:
protected override void ApplyAbpConceptsForAddedEntity(EntityEntry entry, long? userId, EntityChangeReport changeReport)
{
CheckAndSetMustHaveUserIdProperty(entry.Entity, userId);
base.ApplyAbpConceptsForAddedEntity(entry, userId, changeReport);
}
private void CheckAndSetMustHaveUserIdProperty(object entryEntity, long? userId)
{
if (userId == null)
return;
if (!(entryEntity is IMustHaveUser))
{
return;
}
var entity = entryEntity.As<IMustHaveUser>();
entity.UserId = userId.Value;
}