一种始终使用Entity Framework Core过滤查询结果的方法

问题描述 投票:0回答:3

我正在使用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,以便自动处理它们,否则,在每次对数据库的调用中始终处理此问题,这是一个繁琐且容易出错的任务。

任何建议将不胜感激。

asp.net-core entity-framework-core
3个回答
1
投票

检查Global Query Filters

全局查询过滤器是LINQ查询谓词(布尔表达式通常传递给应用于实体的LINQ Where查询运算符)键入元数据模型(通常在OnModelCreating中)。这样的过滤器自动应用于涉及那些实体的任何LINQ查询类型,包括间接引用的实体类型,例如通过使用包含或直接导航属性引用。


0
投票

[在这种情况下,我该做什么的人是创建一个包装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();
    } 
}

0
投票

创建具有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;
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.