.NET 仓储模式入门指南

一、仓储模式是什么?

仓储模式就像是一个"数据管理员":

  • 它负责帮你管理所有与数据存取相关的工作

  • 你的业务代码不需要知道数据是存在数据库、文件还是网络服务中

  • 你只需要告诉仓储"我要什么数据",它就会帮你取来

二、为什么要用仓储模式?

想象你在餐厅点餐:

  • 传统方式:你直接去厨房告诉厨师怎么做菜(业务逻辑直接操作数据库)

  • 仓储模式:你只需要告诉服务员(仓储)你想吃什么,服务员去和厨房沟通

好处:

  • 你不需要关心厨房怎么运作(数据如何存取)

  • 更换厨师(更换数据库)不会影响你点餐

  • 更容易测试(可以用假服务员模拟)

三、实现一个简单的仓储模式

需要安装nuget包

Microsoft.EntityFrameworkCore.Design
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.Tools

在appsettings.json中添加链接数据库链接 

"ConnectionStrings": {
  "DefaultConnection": "server=.;database=BingDbContext;uid=sa;pwd=123456;TrustServerCertificate=True;"
}

1. 项目结构准备

ProductManagement/
├── Controllers/ # WebAPI控制器
├── Models/ # 数据模型
├── Repositories/ # 仓储接口和实现
├── Services/ # 业务逻辑服务(可选)
└── Data/ # 数据库上下文(Entity Framework Core)

2. 创建模型(Model)

// Models/Product.cs
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    public string Description { get; set; }
}

3. 设置数据库上下文

// Data/ApplicationDbContext.cs
using Microsoft.EntityFrameworkCore;
using ProductManagement.Models;

public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) 
        : base(options)
    {
    }

    public DbSet<Product> Products { get; set; }
}

4. 创建仓储接口

// Repositories/IRepository.cs
using System.Collections.Generic;
using System.Threading.Tasks;

public interface IRepository<T> where T : class
{
    Task<IEnumerable<T>> GetAllAsync();
    Task<T> GetByIdAsync(int id);
    Task AddAsync(T entity);
    Task UpdateAsync(T entity);
    Task DeleteAsync(int id);
    Task<bool> ExistsAsync(int id);
}

5. 实现通用仓储

// Repositories/Repository.cs
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ProductManagement.Data;

public class Repository<T> : IRepository<T> where T : class
{
    protected readonly ApplicationDbContext _context;
    protected readonly DbSet<T> _dbSet;

    public Repository(ApplicationDbContext context)
    {
        _context = context;
        _dbSet = context.Set<T>();
    }

    public async Task<IEnumerable<T>> GetAllAsync()
    {
        return await _dbSet.ToListAsync();
    }

    public async Task<T> GetByIdAsync(int id)
    {
        return await _dbSet.FindAsync(id);
    }

    public async Task AddAsync(T entity)
    {
        await _dbSet.AddAsync(entity);
        await _context.SaveChangesAsync();
    }

    public async Task UpdateAsync(T entity)
    {
        _context.Entry(entity).State = EntityState.Modified;
        await _context.SaveChangesAsync();
    }

    public async Task DeleteAsync(int id)
    {
        var entity = await GetByIdAsync(id);
        if (entity != null)
        {
            _dbSet.Remove(entity);
            await _context.SaveChangesAsync();
        }
    }

    public async Task<bool> ExistsAsync(int id)
    {
        var entity = await GetByIdAsync(id);
        return entity != null;
    }
}

6. 创建产品特定仓储接口(可选)

// Repositories/IProductRepository.cs
using System.Collections.Generic;
using System.Threading.Tasks;
using ProductManagement.Models;

public interface IProductRepository : IRepository<Product>
{
    Task<IEnumerable<Product>> GetProductsByPriceRangeAsync(decimal min, decimal max);
}

7. 实现产品特定仓储(可选)

// Repositories/ProductRepository.cs
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ProductManagement.Data;
using ProductManagement.Models;

public class ProductRepository : Repository<Product>, IProductRepository
{
    public ProductRepository(ApplicationDbContext context) : base(context)
    {
    }

    public async Task<IEnumerable<Product>> GetProductsByPriceRangeAsync(decimal min, decimal max)
    {
        return await _context.Products
            .Where(p => p.Price >= min && p.Price <= max)
            .ToListAsync();
    }
}

8. 配置依赖注入

// 在Program.cs中(对于.NET 6+)
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

// 注册通用仓储
builder.Services.AddScoped(typeof(IRepository<>), typeof(Repository<>));

// 注册特定产品仓储(如果使用了特定仓储)
builder.Services.AddScoped<IProductRepository, ProductRepository>();

9. 创建控制器

// Controllers/ProductsController.cs
using Microsoft.AspNetCore.Mvc;
using ProductManagement.Models;
using ProductManagement.Repositories;
using System.Collections.Generic;
using System.Threading.Tasks;

[Route("api/[controller]")]
[ApiController]
public class ProductsController : ControllerBase
{
    private readonly IRepository<Product> _productRepository;

    public ProductsController(IRepository<Product> productRepository)
    {
        _productRepository = productRepository;
    }

    // GET: api/Products
    [HttpGet]
    public async Task<ActionResult<IEnumerable<Product>>> GetProducts()
    {
        return Ok(await _productRepository.GetAllAsync());
    }

    // GET: api/Products/5
    [HttpGet("{id}")]
    public async Task<ActionResult<Product>> GetProduct(int id)
    {
        var product = await _productRepository.GetByIdAsync(id);

        if (product == null)
        {
            return NotFound();
        }

        return product;
    }

    // PUT: api/Products/5
    [HttpPut("{id}")]
    public async Task<IActionResult> PutProduct(int id, Product product)
    {
        if (id != product.Id)
        {
            return BadRequest();
        }

        if (!await _productRepository.ExistsAsync(id))
        {
            return NotFound();
        }

        await _productRepository.UpdateAsync(product);

        return NoContent();
    }

    // POST: api/Products
    [HttpPost]
    public async Task<ActionResult<Product>> PostProduct(Product product)
    {
        await _productRepository.AddAsync(product);
        return CreatedAtAction("GetProduct", new { id = product.Id }, product);
    }

    // DELETE: api/Products/5
    [HttpDelete("{id}")]
    public async Task<IActionResult> DeleteProduct(int id)
    {
        if (!await _productRepository.ExistsAsync(id))
        {
            return NotFound();
        }

        await _productRepository.DeleteAsync(id);

        return NoContent();
    }
}

10. 数据库迁移和应用启动

创建迁移:

dotnet ef migrations add InitialCreate

nuget控制台:

add-migration 添加描述

 

应用迁移:

dotnet ef database update

 nuget控制台迁移

update-database

 

posted @ 2025-04-30 14:08  龙卷风吹毁停车场  阅读(83)  评论(0)    收藏  举报