EfCore HasQueryFilter 方法 v2.2 中的奇怪行为 Expression<Func>(重构问题)
weird behavior Expression<Func> in EfCore HasQueryFilter method v2.2 (Refactoring problem)
我的 AppDbContext EfCore 2.2 中有一个 QueryFilter :
builder.Entity<MessageReceiver> ().HasQueryFilter (
(q) => (q.ReciverId == _uai.LoggedInUserId) ||
(q.Message.SenderId == _uai.LoggedInUserId));
此代码运行良好,因为我注入了自定义服务 (_uai
) 以将登录用户信息检查到我的 AppDbContext 中。
public class AppDbContext : DbContext {
private readonly IUserAccessInfoService _uai;
public AppDbContext (DbContextOptions<AppDbContext> options, IUserAccessInfoService userAccessInfo) : base (options) {
_uai = userAccessInfo;
}
但我无法重构此代码并将整个表达式移动到我的服务中!
将此代码重构为“_uai”服务后,我正在使用它:
builder.Entity<MessageReceiver> ().HasQueryFilter (_uai.GetMessageQueryFilter ());
在我的 'uai' 服务中,我重构了表达式:
// UserAccessInfoService ....
public Expression<Func<MessageReceiver, bool>> GetMessageQueryFilter () {
return (q) =>
(q.ReciverId == LoggedInUserId) ||
(q.Message.SenderId == LoggedInUserId);
}
// this way loggedInUser is null in runtime
表达式是否具有一些内联缓存功能?问题是当我重构这段代码时 EFCore 没有使用注入的服务值,重构后 LoggedInUserId 为 null。
我认为 efcore 对其表达式使用了某种缓存。
全局查询过滤器中使用的表达式是特殊的。特别是,它们仅被评估一次 除了 来自字段 属性 或 DbContext
方法的部分(如在您的原始代码中)。
这在 EF Core Global Query Fiters 文档示例中有部分解释:
Tip
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).
我希望他们在文档中更明确和明确地解释该行为,而不是作为示例的提示,因为这实际上是 唯一的方式 获得动态已评估过滤器。
话虽如此,请保持原始代码不变,或者使用不同的重构方式以备不时之需,以备不时之需 - interface/base class/ EF.Property
或手动表达式组合来绑定 ReceiverId
和 SenderId
表达式,但仍将它们与 this._uai.LoggedInUserId
.
进行比较
我的 AppDbContext EfCore 2.2 中有一个 QueryFilter :
builder.Entity<MessageReceiver> ().HasQueryFilter (
(q) => (q.ReciverId == _uai.LoggedInUserId) ||
(q.Message.SenderId == _uai.LoggedInUserId));
此代码运行良好,因为我注入了自定义服务 (_uai
) 以将登录用户信息检查到我的 AppDbContext 中。
public class AppDbContext : DbContext {
private readonly IUserAccessInfoService _uai;
public AppDbContext (DbContextOptions<AppDbContext> options, IUserAccessInfoService userAccessInfo) : base (options) {
_uai = userAccessInfo;
}
但我无法重构此代码并将整个表达式移动到我的服务中! 将此代码重构为“_uai”服务后,我正在使用它:
builder.Entity<MessageReceiver> ().HasQueryFilter (_uai.GetMessageQueryFilter ());
在我的 'uai' 服务中,我重构了表达式:
// UserAccessInfoService ....
public Expression<Func<MessageReceiver, bool>> GetMessageQueryFilter () {
return (q) =>
(q.ReciverId == LoggedInUserId) ||
(q.Message.SenderId == LoggedInUserId);
}
// this way loggedInUser is null in runtime
表达式是否具有一些内联缓存功能?问题是当我重构这段代码时 EFCore 没有使用注入的服务值,重构后 LoggedInUserId 为 null。 我认为 efcore 对其表达式使用了某种缓存。
全局查询过滤器中使用的表达式是特殊的。特别是,它们仅被评估一次 除了 来自字段 属性 或 DbContext
方法的部分(如在您的原始代码中)。
这在 EF Core Global Query Fiters 文档示例中有部分解释:
Tip
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).
我希望他们在文档中更明确和明确地解释该行为,而不是作为示例的提示,因为这实际上是 唯一的方式 获得动态已评估过滤器。
话虽如此,请保持原始代码不变,或者使用不同的重构方式以备不时之需,以备不时之需 - interface/base class/ EF.Property
或手动表达式组合来绑定 ReceiverId
和 SenderId
表达式,但仍将它们与 this._uai.LoggedInUserId
.