所有文章 > 学习各类API > 深入理解 Repository 模式|.NET Core API 设计最佳实践
深入理解 Repository 模式|.NET Core API 设计最佳实践

深入理解 Repository 模式|.NET Core API 设计最佳实践

1. 引言

在许多 ASP.NET Core 项目中,你可能会看到控制器(Controller)直接引用 DbContext 并写入查询逻辑,导致代码难以维护、难以测试。Repository 模式提供了一种抽象层,将所有与数据库交互的逻辑集中到“仓储”中,实现与业务逻辑层的松耦合。本文用“宝可梦(Pokemon)”示例,带你一步步落地实践。


2. 为什么需要 Repository 模式

  • 降低耦合:控制器和业务层只依赖于接口(而非具体实现),便于替换和测试。
  • 提高复用:将重复的数据库访问逻辑封装在仓储方法中,避免多处粘贴相同代码。
  • 便于单元测试:可对接口打桩(Mock),无需真实数据库即可测试业务逻辑。

3. Repository 模式的两种阐释

3.1 正式定义(学术视角)

> Repository 模式旨在为领域与数据映射层之间提供中介,使业务逻辑层无需关注数据存储细节,就像一个“数据库集合”的接口。

3.2 通俗解释(实战视角)

仓储就是一个专门存放“数据库调用”的地方,你把 DbContext 的增删改查都放在这里,需要时在业务或控制器中“即插即用”,就像随时取用一个独立模块。


4. 在 ASP.NET Core 中实现 Repository 模式

4.1 定义模型(Pokemon)

public class Pokemon
{
    public int Id { get; set; }
    public string Name { get; set; }
    // … 其他属性
}

4.2 创建接口(IPokemonRepository)

Interfaces/IPokemonRepository.cs 中定义仓储契约:

public interface IPokemonRepository
{
    IReadOnlyCollection < Pokemon > GetPokemons();
    // 若有增删改查,可继续扩展:
    // Pokemon GetPokemon(int id);
    // bool CreatePokemon(Pokemon p);
    // bool UpdatePokemon(Pokemon p);
    // bool DeletePokemon(int id);
}

4.3 编写仓储类(PokemonRepository)


Repositories/PokemonRepository.cs 中实现接口:

public class PokemonRepository : IPokemonRepository
{
    private readonly AppDbContext _context;

    public PokemonRepository(AppDbContext context)
    {
        _context = context;
    }

    public IReadOnlyCollection < Pokemon > GetPokemons()
    {
        // 从 DbContext 中读取所有 Pokemons,并按 Id 排序
        return _context.Pokemons
                       .OrderBy(p = > p.Id)
                       .ToList();
    }
}

> 要点ToList() 明确触发查询,并转换为不可变集合类型。


4.4 在 Controller 中调用仓储方法

Controllers/PokemonController.cs 中注入并使用:

[ApiController]
[Route("api/[controller]")]
public class PokemonController : ControllerBase
{
    private readonly IPokemonRepository _pokemonRepo;

    public PokemonController(IPokemonRepository pokemonRepo)
    {
        _pokemonRepo = pokemonRepo;
    }

    [HttpGet]
    public ActionResult < IReadOnlyCollection < Pokemon > > GetPokemons()
    {
        if (!ModelState.IsValid)
            return BadRequest(ModelState);

        var list = _pokemonRepo.GetPokemons();
        return Ok(list);
    }
}
  • 通过接口注入,对控制器隐藏了具体仓储实现细节。

4.5 配置依赖注入

Program.cs 中注册服务:

builder.Services.AddScoped < IPokemonRepository, PokemonRepository > ();
  • AddScoped:作用域级别注入,适合每次 HTTP 请求中使用同一实例。

5. 小结与最佳实践

  • 接口先行:始终先定义契约接口,再实现类。
  • 单一职责:仓储只负责数据访问,不要混入业务逻辑。
  • 依赖注入:通过 DI 容器注入接口,解耦控制器与实现。
  • 可测试性:在单元测试中对接口打桩,隔离数据库依赖。
  • 按需扩展:根据项目需求,为每个实体创建独立仓储,或抽象通用仓储基类。

通过本文示例,你已掌握在 ASP.NET Core 项目中从零搭建 Repository 模式的全流程,让你的 API 更加松耦合、易维护、可测试。继续打磨、优化,项目将更具健壮性与可扩展性!

原文引自YouTube视频:https://www.youtube.com/watch?v=-LAeEQSfOQk

#你可能也喜欢这些API文章!

我们有何不同?

API服务商零注册

多API并行试用

数据驱动选型,提升决策效率

查看全部API→
🔥

热门场景实测,选对API

#AI文本生成大模型API

对比大模型API的内容创意新颖性、情感共鸣力、商业转化潜力

25个渠道
一键对比试用API 限时免费

#AI深度推理大模型API

对比大模型API的逻辑推理准确性、分析深度、可视化建议合理性

10个渠道
一键对比试用API 限时免费