我正在使用EF作为对数据库进行分区的方式在ASP.NET应用程序中的所有模型上使用OrgID
。我这样做是为了可以在多个用户之间共享数据库,同时确保只有他们所在组织的数据可供他们使用。
这迫使我在每次插入时都写上这个OrgID
,并过滤我对数据库的每次调用。
例如,我查询当前用户的OrgID
,并将其插入到控制器的Update
方法中,如下所示:
store.OrgID = await _userManager.GetUserAsync(User).OrgID;
_context.Update(store);
await _context.SaveChangesAsync();
然后,当我想列出对象时,我再次需要按OrgID
进行过滤:
var orgID = await _userManager.GetUserAsync(User).OrgID;
var stores = await _context.Stores.Where(s => s.OrgID == orgID).ToListAsync();
我很想找到一种方法来覆盖ApplicationDBContext
,以便自动处理它们,否则,在每次对数据库的调用中始终处理此问题,这是一个繁琐且容易出错的任务。
任何建议将不胜感激。
全局查询过滤器是LINQ查询谓词(布尔表达式通常传递给应用于实体的LINQ Where查询运算符)键入元数据模型(通常在OnModelCreating中)。这样的过滤器自动应用于涉及那些实体的任何LINQ查询类型,包括间接引用的实体类型,例如通过使用包含或直接导航属性引用。
[在这种情况下,我该做什么的人是创建一个包装DbContext
的类,并公开对其业务逻辑有意义的方法。在您的情况下,您可以创建UserRepository
/ StoreRepository
类,其中搜索方法需要origID
参数
public class StoreRepository {
private ApplicationDBContext _context
StoreRepository(ApplicationDBContext context){
_context = context
}
public Task<Ilist<Store>> GetStores(int origID){
return _context.Stores.Where(s => s.OrgID == orgID).ToListAsync();
}
}
创建具有OrgID的接口:
public interface IOrgID
{
public int OrgID { get; set; }
}
您的所有模型都必须实现此接口,例如:
public class ApplicationUser : IdentityUser, IOrgID
{
public int OrgID { get; set; }
//...
}
public class Stores : IOrgID
{
public int OrgID { get; set; }
//...
}
使用通用存储库并考虑当前登录用户的OrgID创建CRUD方法:
public class MyRepo
{
private readonly ApplicationDbContext _context;
private readonly IHttpContextAccessor _accessor;
private readonly int _orgID;
public MyRepo(ApplicationDbContext context, IHttpContextAccessor accessor)
{
_context = context;
_accessor = accessor;
var userId = _accessor.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier);
_orgID = _context.Users.Find(userId).OrgID;
}
public async Task<T> GetAsync<T>(Expression<Func<T, bool>> whereExp)
where T : class, IOrgId
{
return await _context.Set<T>().Where(x => x.OrgId == _orgID).FirstOrDefaultAsync(whereExp);
}
public async Task<bool> UpdateAsync<T>(T entity)
where T : class, IOrgId
{
_context.Entry<T>(entity).State = EntityState.Modified;
return await _context.SaveChangesAsync() > 0;
}
public async Task<IEnumerable<T>> ListAsync<T>(Expression<Func<T, bool>> whereExp)
where T : class, IOrgId
{
return await _context.Set<T>().AsNoTracking().Where(x => x.OrgId == _orgID).Where(whereExp).ToListAsync();
}
public async Task<bool> DeleteAync<T>(T entity)
where T : class, IOrgId
{
_context.Entry<T>(entity).State = EntityState.Deleted;
return await _context.SaveChangesAsync() > 0;
}
}