撰于 阅读 25

使用 EF Core 8 实现简单的 Unit of Work 和 Repository 模式

在现代应用程序中,使用 Repository 和 Unit of Work 模式能够有效地管理数据访问和事务。这篇文章将介绍如何在 .NET 8 中使用 Entity Framework Core (EF Core 8) 实现这两个模式。

1. 环境准备

确保你的开发环境已安装以下工具:

  • .NET 8 SDK
  • Visual Studio 或其他 C# 开发工具
  • EF Core NuGet 包

在你的项目中安装 EF Core 包:

dotnet add package Microsoft.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools

2. 创建模型和上下文

首先,创建一个简单的模型和数据库上下文。

2.1 创建模型

创建一个 Product 类作为示例模型:

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}

2.2 创建数据库上下文

创建一个 AppDbContext 类,继承自 DbContext

using Microsoft.EntityFrameworkCore;

public class AppDbContext : DbContext
{
    public DbSet<Product> Products { get; set; }

    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Product>().ToTable("Products");
    }
}

3. 实现 Repository 模式

接下来,创建一个通用的 Repository 接口和实现类。

3.1 创建 IRepository 接口

using System.Linq.Expressions;

public interface IRepository<T> where T : class
{
    Task<T> GetByIdAsync(int id);
    Task<IEnumerable<T>> GetAllAsync();
    Task<IEnumerable<T>> FindAsync(Expression<Func<T, bool>> predicate);
    Task AddAsync(T entity);
    void Update(T entity);
    void Delete(T entity);
}

3.2 实现 Repository

using Microsoft.EntityFrameworkCore;

public class Repository<T> : IRepository<T> where T : class
{
    private readonly AppDbContext _context;
    private readonly DbSet<T> _dbSet;

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

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

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

    public async Task<IEnumerable<T>> FindAsync(Expression<Func<T, bool>> predicate)
    {
        return await _dbSet.Where(predicate).ToListAsync();
    }

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

    public void Update(T entity)
    {
        _dbSet.Update(entity);
    }

    public void Delete(T entity)
    {
        _dbSet.Remove(entity);
    }
}

4. 实现 Unit of Work 模式

接下来,创建一个 Unit of Work 接口和实现类。

4.1 创建 IUnitOfWork 接口

public interface IUnitOfWork : IDisposable
{
    IRepository<Product> Products { get; }
    Task<int> SaveAsync();
}

4.2 实现 Unit of Work

public class UnitOfWork : IUnitOfWork
{
    private readonly AppDbContext _context;

    public UnitOfWork(AppDbContext context)
    {
        _context = context;
        Products = new Repository<Product>(_context);
    }

    public IRepository<Product> Products { get; private set; }

    public async Task<int> SaveAsync()
    {
        return await _context.SaveChangesAsync();
    }

    public void Dispose()
    {
        _context.Dispose();
    }
}

5. 使用 Unit of Work 和 Repository

在你的服务或控制器中使用 Unit of Work 和 Repository:

public class ProductService
{
    private readonly IUnitOfWork _unitOfWork;

    public ProductService(IUnitOfWork unitOfWork)
    {
        _unitOfWork = unitOfWork;
    }

    public async Task<Product> CreateProductAsync(Product product)
    {
        await _unitOfWork.Products.AddAsync(product);
        await _unitOfWork.SaveAsync();
        return product;
    }

    public async Task<IEnumerable<Product>> GetAllProductsAsync()
    {
        return await _unitOfWork.Products.GetAllAsync();
    }
}

6. 配置依赖注入

Program.cs 中配置依赖注入:

var builder = WebApplication.CreateBuilder(args);

// 添加 EF Core 上下文
builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

// 注册 UnitOfWork
builder.Services.AddScoped<IUnitOfWork, UnitOfWork>();

var app = builder.Build();

7. 结论

通过以上步骤,你已成功实现了简单的 Unit of Work 和 Repository 模式。这个模式有助于提高代码的可维护性和可测试性。你可以根据自己的需求进一步扩展此实现,例如添加更多的实体或复杂的查询逻辑。希望这篇文章能对你有所帮助!