是否可以在一行中写下以下内容?
//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 for Item和Invite,但是EF抛出了一个错误,说它必须是一个引用类型。
我也尝试了一个基类,但我不想改变基本表,这似乎是完成这项工作所必需的。
还有其他选择吗?
答案 0 :(得分:6)
假设您的实体实现以下界面:
public interface ITenantEntity
{
int TenantId { get; set; }
}
使用公共代码通过流畅的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);