c# - 基于接口的全局过滤器
问题描述
是否可以在一行中写下以下内容?
//Create a Global Filter for the TenantId property.
modelBuilder.Entity<Item>().HasQueryFilter(b => EF.Property<int>(b, "TenantId") == this._appUserProvider.CurrentTenantId);
modelBuilder.Entity<Invite>().HasQueryFilter(b => EF.Property<int>(b, "TenantId") == this._appUserProvider.CurrentTenantId);
我尝试了 Item 和 Invite 的接口,但 EF 抛出错误,说它必须是引用类型。
我还尝试了一个基类,但我不想更改似乎需要使其工作的基表。
还有其他选择吗?
解决方案
假设您的实体实现了以下接口:
public interface ITenantEntity
{
int TenantId { get; set; }
}
使用通用代码通过 fluent API 配置多个实体时,最重要的是调用时使用真实的实体类型modelBuilder.Entity<TEntity>()
。使用基类会引入 EF 继承,接口只会产生异常。
IMO 最简单的解决方案是将通用代码放在通用方法中并通过反射调用它。
DbContext
首先在包含所需流畅配置的派生类中创建一个受约束的通用实例方法:
void ConfigureTenantFilter<TEntity>(ModelBuilder modelBuilder)
where TEntity : class, ITenantEntity
{
modelBuilder.Entity<TEntity>()
.HasQueryFilter(e => e.TenantId == this._appUserProvider.CurrentTenantId);
}
然后在覆盖结束时使用以下代码段OnModelCreating
(在发现所有实体类型之后):
var configureTenantMethod = GetType().GetTypeInfo().DeclaredMethods.Single(m => m.Name == nameof(ConfigureTenantFilter));
var args = new object[] { modelBuilder };
var tenantEntityTypes = modelBuilder.Model.GetEntityTypes()
.Where(t => typeof(ITenantEntity).IsAssignableFrom(t.ClrType));
foreach (var entityType in tenantEntityTypes)
configureTenantMethod.MakeGenericMethod(entityType.ClrType).Invoke(this, args);
推荐阅读
- javascript - 加载ajax时变量不保留值
- docker - 大厅中的 docker-image 和 registry-image 有什么区别?
- javascript - querySelectorAll 不在父级中的元素 display: none
- reactjs - 在本机反应中将动态变量传递给`flatListProps`中的`renderItem`
- arrays - 在 JSONB 数组中强制唯一性
- mysql - Mysql 是否省略尾随空格?
- ios - 如何使用 DispatchQueue 使视图在一段时间后出现和消失?
- java - 如何从 Android Studio 中的实时 Firebase 检索特定用户
- r - str_extract 带有引号和分号的正则表达式
- c++ - 在 C++ 中请求条件信息