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

.NET C#中Repository模式的自定义错误返回问题

.NET C# Repository模式下服务层错误区分的推荐方案

针对你遇到的服务层返回null无法区分错误类型的问题,以下是两种工业界常用的优雅解决方案:


方案一:自定义业务异常+全局异常处理

通过定义特定业务异常,服务层抛出对应异常,配合全局过滤器统一处理,避免控制器冗余代码。

1. 定义业务异常类

// 账户不存在异常
public class AccountNotFoundException : Exception
{
    public AccountNotFoundException(string message) : base(message) { }
}

// 余额不足异常
public class InsufficientBalanceException : Exception
{
    public InsufficientBalanceException(string message) : base(message) { }
}

2. 服务层抛出对应异常

public async Task<Account> WithdrawAsync(Guid accountId, decimal amount)
{
    var account = await _accountRepository.GetByIdAsync(accountId);
    if (account == null)
    {
        throw new AccountNotFoundException($"账户 {accountId} 不存在");
    }
    if (account.Balance < amount)
    {
        throw new InsufficientBalanceException($"账户 {accountId} 余额不足,当前余额:{account.Balance}");
    }

    account.Balance -= amount;
    await _accountRepository.UpdateAsync(account);
    return account;
}

3. 全局异常过滤器处理

在Program.cs中注册全局过滤器:

builder.Services.AddControllers(options =>
{
    options.Filters.Add<GlobalExceptionFilter>();
});

// 全局异常处理过滤器
public class GlobalExceptionFilter : IExceptionFilter
{
    public void OnException(ExceptionContext context)
    {
        var (statusCode, response) = context.Exception switch
        {
            AccountNotFoundException ex => (StatusCodes.Status404NotFound, new { Message = ex.Message }),
            InsufficientBalanceException ex => (StatusCodes.Status400BadRequest, new { Message = ex.Message }),
            _ => (StatusCodes.Status500InternalServerError, new { Message = "服务器内部错误" })
        };

        context.Result = new ObjectResult(response) { StatusCode = statusCode };
        context.ExceptionHandled = true;
    }
}

方案二:Result模式(自定义结果类)

通过封装包含状态、数据、错误信息的通用结果类,显式返回操作状态,适合需要更精准控制返回逻辑的场景。

1. 定义通用Result类和错误枚举

public enum BusinessErrorType
{
    None,
    AccountNotFound,
    InsufficientBalance
}

public class Result<T>
{
    public bool IsSuccess { get; }
    public T Data { get; }
    public string ErrorMessage { get; }
    public BusinessErrorType ErrorType { get; }

    private Result(bool isSuccess, T data, string errorMessage, BusinessErrorType errorType)
    {
        IsSuccess = isSuccess;
        Data = data;
        ErrorMessage = errorMessage;
        ErrorType = errorType;
    }

    // 成功结果构造方法
    public static Result<T> Success(T data) => new(true, data, null, BusinessErrorType.None);
    // 失败结果构造方法
    public static Result<T> Failure(string message, BusinessErrorType errorType) => new(false, default, message, errorType);
}

2. 服务层返回Result对象

public async Task<Result<Account>> WithdrawAsync(Guid accountId, decimal amount)
{
    var account = await _accountRepository.GetByIdAsync(accountId);
    if (account == null)
    {
        return Result<Account>.Failure($"账户 {accountId} 不存在", BusinessErrorType.AccountNotFound);
    }
    if (account.Balance < amount)
    {
        return Result<Account>.Failure($"账户 {accountId} 余额不足,当前余额:{account.Balance}", BusinessErrorType.InsufficientBalance);
    }

    account.Balance -= amount;
    await _accountRepository.UpdateAsync(account);
    return Result<Account>.Success(account);
}

3. 控制器处理Result

[HttpPost("withdraw")]
public async Task<IActionResult> Withdraw(Guid accountId, decimal amount)
{
    var result = await _accountService.WithdrawAsync(accountId, amount);
    
    if (!result.IsSuccess)
    {
        return result.ErrorType switch
        {
            BusinessErrorType.AccountNotFound => NotFound(result.ErrorMessage),
            BusinessErrorType.InsufficientBalance => BadRequest(result.ErrorMessage),
            _ => StatusCode(StatusCodes.Status500InternalServerError, result.ErrorMessage)
        };
    }

    return Ok(result.Data);
}

方案对比

  • 自定义异常方案:代码简洁,适合业务错误属于“异常场景”的情况,全局处理避免重复代码。
  • Result模式:更显式,无需依赖异常机制,适合需要精准控制返回逻辑的场景,并非不良实践,很多成熟.NET框架(如MediatR、ABP)都有类似实现。

不建议在控制器中逐个方法写try-catch,会导致代码冗余,全局异常处理或Result模式是更优选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 00:26:21