在 EF Core fds 中使用 Runtime Data 过滤 HasQueryFilter() 中的行
Use Runtime Data to filter Rows in HasQueryFilter() in EF Core fds
在我的应用程序中有一个名为 RecordType
的枚举,所有表都包含一个名为 'TypeId' 的字段。
当用户添加一条新记录时,我根据用户的TypeId设置TypeId
。通过这种方式,我想加载与每个用户类型相关的数据。
RecordType
是:
public enum RecordType
{
None=0,
Programmers = 1,
Marketer = 3,
Financial = 5,
}
当用户以 Programmer
类型登录系统时,我必须只加载类型为 'Programmer' 的用户添加的所有数据。
我想使用 HasQueryFilter()
,但据我所知,它只能用于静态字段,不能使用 currentUserId
,因为在 运行 应用程序之后是可能的。
我添加了这样的扩展方法:
public static class QueryFilterExtensions
{
public static IQueryable<TEntity> FilterByUser<TEntity>(this IQueryable<TEntity> query, ICurrentUserService currentUser) where TEntity : BaseEntity
{
if (currentUser.TypeId != Domain.Enums.RecordType.None)
query = query.Where(e => e.TypeId == currentUser.TypeId);
return query;
}
}
以这种方式,我必须在阅读的所有部分中重新调用此扩展方法,如下所示。
return await _dbContext.Groups.OrderBy(x => x.Id)
.FilterByUser(_currentUser)
.ProjectTo<GroupDto>(_mapper.ConfigurationProvider)
.PaginatedListAsync(request.PageIndex, request.PageSize);
I wanted to use HasQueryFilter()
but As I know it just work with static fields and can not use currentUserId beacuse it is possible after running application.
实际上这是可能的,但文档很少 - 就像 Global Query Filters 文档主题示例的提示:
Note the use of a DbContext
instance level field: _tenantId
used to set the current tenant. Model-level filters will use the value from the correct context instance (that is, the instance that is executing the query).
它的真正含义和应该记录在案的是,不是来自参数或不是常量的全局过滤器查询表达式部分必须 rooted 在上下文 class为了动态。或者换句话说,必须源自上下文 class.
的 property/field/method
例如,如果您的上下文有 属性
public RecordType CurrentUserTypeId => // coming from injected service or something
然后您可以在全局查询过滤器中使用,它将针对每个上下文进行动态评估。您可以在您的上下文 class
中使用类似的内容进行一般设置
void SetQueryFilter<TEntity>(ModelBuilder modelBuilder)
where TEntity : BaseEntity
{
modelBuilder.Entity<TEntity>().HasQueryFilter(
e => this.CurrentUserTypeId == RecordType.None || e.TypeId == this.CurrentUserTypeId);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// other stuff...
var setQueryFilterMethod = new Action<ModelBuilder>(SetQueryFilter<MyBaseEntity>)
.Method.GetGenericMethodDefinition();
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
if (entityType.BaseType == null && typeof(BaseEntity).IsAssignableFrom(entityType.ClrType))
{
setQueryFilterMethod
.MakeGenericMethod(entityType.ClrType)
.Invoke(this, new object[] { modelBuilder });
}
}
}
在我的应用程序中有一个名为 RecordType
的枚举,所有表都包含一个名为 'TypeId' 的字段。
当用户添加一条新记录时,我根据用户的TypeId设置TypeId
。通过这种方式,我想加载与每个用户类型相关的数据。
RecordType
是:
public enum RecordType
{
None=0,
Programmers = 1,
Marketer = 3,
Financial = 5,
}
当用户以 Programmer
类型登录系统时,我必须只加载类型为 'Programmer' 的用户添加的所有数据。
我想使用 HasQueryFilter()
,但据我所知,它只能用于静态字段,不能使用 currentUserId
,因为在 运行 应用程序之后是可能的。
我添加了这样的扩展方法:
public static class QueryFilterExtensions
{
public static IQueryable<TEntity> FilterByUser<TEntity>(this IQueryable<TEntity> query, ICurrentUserService currentUser) where TEntity : BaseEntity
{
if (currentUser.TypeId != Domain.Enums.RecordType.None)
query = query.Where(e => e.TypeId == currentUser.TypeId);
return query;
}
}
以这种方式,我必须在阅读的所有部分中重新调用此扩展方法,如下所示。
return await _dbContext.Groups.OrderBy(x => x.Id)
.FilterByUser(_currentUser)
.ProjectTo<GroupDto>(_mapper.ConfigurationProvider)
.PaginatedListAsync(request.PageIndex, request.PageSize);
I wanted to use
HasQueryFilter()
but As I know it just work with static fields and can not use currentUserId beacuse it is possible after running application.
实际上这是可能的,但文档很少 - 就像 Global Query Filters 文档主题示例的提示:
Note the use of a
DbContext
instance level field:_tenantId
used to set the current tenant. Model-level filters will use the value from the correct context instance (that is, the instance that is executing the query).
它的真正含义和应该记录在案的是,不是来自参数或不是常量的全局过滤器查询表达式部分必须 rooted 在上下文 class为了动态。或者换句话说,必须源自上下文 class.
的 property/field/method例如,如果您的上下文有 属性
public RecordType CurrentUserTypeId => // coming from injected service or something
然后您可以在全局查询过滤器中使用,它将针对每个上下文进行动态评估。您可以在您的上下文 class
中使用类似的内容进行一般设置
void SetQueryFilter<TEntity>(ModelBuilder modelBuilder)
where TEntity : BaseEntity
{
modelBuilder.Entity<TEntity>().HasQueryFilter(
e => this.CurrentUserTypeId == RecordType.None || e.TypeId == this.CurrentUserTypeId);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// other stuff...
var setQueryFilterMethod = new Action<ModelBuilder>(SetQueryFilter<MyBaseEntity>)
.Method.GetGenericMethodDefinition();
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
if (entityType.BaseType == null && typeof(BaseEntity).IsAssignableFrom(entityType.ClrType))
{
setQueryFilterMethod
.MakeGenericMethod(entityType.ClrType)
.Invoke(this, new object[] { modelBuilder });
}
}
}