我希望能够自动过滤表中名为TenantID的列中所有生成的实体,并在保存时自动插入登录用户的TenantID。
部分类示例:
public partial class Filtered_Db_Context : MyDbContext
{
private int _tenant;
public Filtered_Db_Context(IHttpContextAccessor context) : base()
{
_tenant = AuthenticationMethods.GetTenantId(context?.HttpContext);
}
public Filtered_Db_Context(HttpContext context) : base()
{
_tenant = AuthenticationMethods.GetTenantId(context);
}
public void AddTenantFilter<T>(ModelBuilder mb) where T : class
{
mb.Entity<T>().HasQueryFilter(t => EF.Property<int>(t, "TenantId") == _tenant);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
//For any entity that has a TenantId it will only allow logged in user to see data from their own Tenant
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
var prop = entityType.FindProperty("TenantId");
if (prop != null && prop.ClrType == typeof(int))
{
GetType()
.GetMethod(nameof(AddTenantFilter))
.MakeGenericMethod(entityType.ClrType)
.Invoke(this, new object[] { modelBuilder });
}
}
}
public override int SaveChanges(bool acceptAllChangesOnSuccess)
{
InsertTenantId();
return base.SaveChanges(acceptAllChangesOnSuccess);
}
public override int SaveChanges()
{
InsertTenantId();
return base.SaveChanges();
}
public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
{
InsertTenantId();
return base.SaveChangesAsync(cancellationToken);
}
public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default(CancellationToken))
{
InsertTenantId();
return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
}
private void InsertTenantId()
{
if (_tenant != 0)
{
var insertedOrUpdated = ChangeTracker.Entries().Where(e => e.State == EntityState.Added || e.State == EntityState.Modified).ToList();
insertedOrUpdated.ForEach(e => {
var prop = e.Property("TenantId");
int propIntVal;
bool isIntVal = int.TryParse(prop.CurrentValue.ToString(), out propIntVal);
if (prop != null && prop.Metadata.IsForeignKey() && isIntVal && propIntVal != _tenant)
{
prop.CurrentValue = _tenant;
}
});
}
}
}
现在您可以使用
Filtered_Db_Context
只需在启动时将其添加到依赖项注入,而不是EF生成的上下文:
serivces.AddDbContext<Filtered_Db_Context>()
当您重新构建scaffold时,不需要进入并编辑任何生成的类。