You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EF Core中如何更优雅地实现按角色区分数据查询?

更优雅的角色数据过滤实现方式

针对你当前的角色数据过滤需求,这里提供几种更简洁、可维护的实现方案,适配不同复杂度的场景:

1. 条件链式拼接过滤(适合简单场景)

将过滤逻辑拆分为线性的条件拼接,避免分支直接返回,让代码结构更清晰,同时方便后续统一处理分页、数据转换等逻辑:

public async Task<PagedResponse<TodoItemBriefDto>> Handle(GetTodoItemsWithPaginationQuery request, CancellationToken cancellationToken)
{
    var query = _context.Set<TodoItemExample>().AsQueryable();
    
    // 根据角色动态添加过滤条件
    if (request.User.RoleId == "OPERATOR")
    {
        query = query.Where(x => x.UserId == request.User.Id);
    }
    
    // 统一处理分页与数据转换
    var totalCount = await query.CountAsync(cancellationToken);
    var items = await query
        .Skip((request.PageNumber - 1) * request.PageSize)
        .Take(request.PageSize)
        .ProjectTo<TodoItemBriefDto>(_mapper.ConfigurationProvider)
        .ToListAsync(cancellationToken);
    
    return new PagedResponse<TodoItemBriefDto>(items, totalCount, request.PageNumber, request.PageSize);
}

2. 扩展方法封装过滤逻辑(提升代码可读性)

将角色过滤逻辑封装为扩展方法,让业务方法更专注于核心流程,同时过滤逻辑可复用:

首先定义扩展方法:

public static class TodoItemQueryExtensions
{
    public static IQueryable<TodoItemExample> FilterByUserRole(this IQueryable<TodoItemExample> query, User user)
    {
        return user.RoleId == "OPERATOR" 
            ? query.Where(x => x.UserId == user.Id) 
            : query;
    }
}

然后在Handle中调用:

public async Task<PagedResponse<TodoItemBriefDto>> Handle(GetTodoItemsWithPaginationQuery request, CancellationToken cancellationToken)
{
    var query = _context.Set<TodoItemExample>()
        .FilterByUserRole(request.User);
    
    // 后续分页与转换逻辑同上
}

3. 策略模式(适合复杂/可扩展场景)

如果未来可能新增角色、扩展过滤逻辑,策略模式能避免大量if-else分支,符合开闭原则:

步骤1:定义策略接口

public interface ITodoItemQueryStrategy
{
    IQueryable<TodoItemExample> ApplyFilter(IQueryable<TodoItemExample> query, User user);
}

步骤2:实现各角色策略

// Admin角色策略:无过滤
public class AdminTodoQueryStrategy : ITodoItemQueryStrategy
{
    public IQueryable<TodoItemExample> ApplyFilter(IQueryable<TodoItemExample> query, User user)
    {
        return query;
    }
}

// Operator角色策略:过滤自己的数据
public class OperatorTodoQueryStrategy : ITodoItemQueryStrategy
{
    public IQueryable<TodoItemExample> ApplyFilter(IQueryable<TodoItemExample> query, User user)
    {
        return query.Where(x => x.UserId == user.Id);
    }
}

步骤3:在Handler中使用策略

通过依赖注入注入策略字典,根据角色获取对应策略:

private readonly Dictionary<string, ITodoItemQueryStrategy> _strategyMap;

public GetTodoItemsWithPaginationQueryHandler(Dictionary<string, ITodoItemQueryStrategy> strategyMap)
{
    _strategyMap = strategyMap;
}

public async Task<PagedResponse<TodoItemBriefDto>> Handle(GetTodoItemsWithPaginationQuery request, CancellationToken cancellationToken)
{
    // 匹配策略,默认用Admin策略
    var strategy = _strategyMap.TryGetValue(request.User.RoleId, out var matchedStrategy) 
        ? matchedStrategy 
        : _strategyMap["ADMIN"];
    
    var query = strategy.ApplyFilter(_context.Set<TodoItemExample>(), request.User);
    
    // 后续分页与转换逻辑同上
}

内容的提问来源于stack exchange,提问作者Lube

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 02:00:38