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

如何在.NET Core泛型仓储中基于表达式实现Lookup表的FindByID功能

现有代码存在的问题

  • 仓储层GetById方法调用Where返回的是IQueryable<T>集合,直接映射会得到错误结果,且未实现异步逻辑
  • 服务层方法未声明predicate参数、未加async标记,且查询操作不需要调用_unitOfWork.CompleteAsync()(仅增删改需要提交事务)
  • 控制器的接口未接收前端传入的Id参数,路由配置不符合Restful规范

修正后的实现方案

1. 增加Lookup实体统一约束

先定义公共接口,保证所有Lookup表都有Id和Value字段,方便泛型约束:

public interface ILookupEntity
{
    int Id { get; set; }
    string Value { get; set; }
}

给所有Lookup实体实现该接口:

public partial class LutGender : ILookupEntity
{
    public int Id { get; set; }
    public string Value { get; set; }
}

public partial class LutNationality : ILookupEntity
{
    public int Id { get; set; }
    public string Value { get; set; }
}

2. 修正泛型仓储实现

建议直接封装Id查询逻辑,避免外部传入不合理的表达式影响性能:

// 泛型仓储接口增加约束
public interface IGenericRepository<T> where T : class, ILookupEntity
{
    Task<GenericLookupDTO> GetByIdAsync(int id);
}

// 仓储实现
public class GenericRepository<T> : IGenericRepository<T> where T : class, ILookupEntity
{
    private readonly NexusContext _context;
    public GenericRepository(NexusContext context)
    {
        _context = context;
    }
    public async Task<GenericLookupDTO> GetByIdAsync(int id)
    {
        var obj = await _context.Set<T>().FirstOrDefaultAsync(x => x.Id == id);
        return AutoMapping.mapper.Map<GenericLookupDTO>(obj);
    }
}

3. 修正服务层实现

补全方法签名和异步标记:

// 服务接口定义
public interface IConfigurationService<T> where T : class, ILookupEntity
{
    Task<GenericResponse<GenericLookupDTO>> GetByIdAsync(int id);
}

// 服务实现
public class ConfigurationService<T> : IConfigurationService<T> where T : class, ILookupEntity
{
    private readonly IGenericRepository<T> _genericRepository;
    private readonly IUnitOfWork _unitOfWork;

    public ConfigurationService(IGenericRepository<T> genericRepository, IUnitOfWork unitOfWork)
    {
        _genericRepository = genericRepository;
        _unitOfWork = unitOfWork;
    }

    public async Task<GenericResponse<GenericLookupDTO>> GetByIdAsync(int id)
    {
        List<Errors> errors = new List<Errors>();
        try
        {
            var obj = await _genericRepository.GetByIdAsync(id);
            if (obj == null)
            {
                errors.Add(new Errors("404", "Couldn't find configuration"));
                return new GenericResponse<GenericLookupDTO>(errors, new GenericLookupDTO());
            }
            return new GenericResponse<GenericLookupDTO>("1", "Success", obj);
        }
        catch (Exception ex)
        {
            var errorMsg = ex.InnerException?.Message ?? ex.Message;
            errors.Add(new Errors(ex.HResult.ToString(), errorMsg));
            return new GenericResponse<GenericLookupDTO>(errors, new GenericLookupDTO());
        }
    }
}

4. 修正控制器调用逻辑

private readonly IConfigurationService<LutNationality> _configurationService;
public NationalityController(IConfigurationService<LutNationality> configurationService)
{
    _configurationService = configurationService;
}

// 路由配置接收id参数,比如请求地址为 GET /Nationality/1
[HttpGet("{id:int}")]
[ProducesResponseType(typeof(GenericLookupDTO), (int)HttpStatusCode.OK)]
public async Task<IActionResult> GetByIdAsync([FromRoute] int id)
{
    var result = await _configurationService.GetByIdAsync(id);
    if (result.operationSuccess)
        return Ok(result);
    return BadRequest(result);
}

若坚持使用表达式传参的方案

如果要保留原有的表达式参数设计,控制器调用时直接传入匹配条件即可:

var result = await _configurationService.GetByIdAsync(x => x.Id == id);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 15:09:00