工作单元(Unit of Work, UoW)模式是一种用于处理事务性工作的方法,特别适用于需要对数据库进行多次操作时。它的主要目的是将多个数据库操作封装在一个事务中,确保所有操作能整体成功或者整体失败,从而保证数据的一致性。
本文将详细介绍如何在 C# 中实现工作单元模式,并提供完整的代码注释。
工作单元模式的关键概念
- 工作单元(Unit of Work):一个类,它封装了一个业务事务的多个操作,并记录对这些操作的更改。
- 仓储(Repository):一个类,它管理实体的持久化,并通常与工作单元合作。
- 事务管理:确保多次数据库操作要么全部成功,要么全部回滚。
实现步骤
下面是实现工作单元模式的步骤:
- 定义实体类。
- 定义仓储接口和实现。
- 定义工作单元接口和实现。
- 使用工作单元及其仓储。
1. 定义实体类
首先,我们定义一个简单的实体类 Product。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AppUnitWork
{
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
}
2. 定义仓储接口和实现
接下来,定义各种实体的仓储接口和实现。这里以 Product 为例。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AppUnitWork
{
public interface IProductRepository
{
IEnumerable<Product> GetAll();
Product GetById(int id);
void Add(Product product);
void Update(Product product);
void Delete(int id);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AppUnitWork
{
public class ProductRepository : IProductRepository
{
private readonly AppDbContext _context;
public ProductRepository(AppDbContext context)
{
_context = context;
}
public IEnumerable<Product> GetAll() => _context.Products.ToList();
public Product GetById(int id) => _context.Products.Find(id);
public void Add(Product product)
{
_context.Products.Add(product);
}
public void Update(Product product)
{
_context.Products.Update(product);
}
public void Delete(int id)
{
var product = _context.Products.Find(id);
if (product != null)
{
_context.Products.Remove(product);
}
}
}
}
3. 定义工作单元接口和实现
定义工作单元以管理多个仓储和事务。
public interface IUnitOfWork : IDisposable
{
IProductRepository Products { get; }
int Complete();
}
public class UnitOfWork : IUnitOfWork
{
private readonly AppDbContext _context;
public IProductRepository Products { get; private set; }
public UnitOfWork(AppDbContext context, IProductRepository productRepository)
{
_context = context;
Products = productRepository;
}
public int Complete()
{
return _context.SaveChanges();
}
public void Dispose()
{
_context.Dispose();
}
}
4. 使用工作单元及其仓储
示例调用代码展示了如何使用工作单元和仓储来实现多个数据库操作的事务管理。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AppUnitWork
{
public class ProductService
{
private readonly IUnitOfWork _unitOfWork;
public ProductService(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public void PerformProductOperations()
{
// 增加新产品
var newProduct = new Product { Name = "New Product", Price = 99.99m };
_unitOfWork.Products.Add(newProduct);
_unitOfWork.Complete();
Console.WriteLine("Added new product");
// 更新现有产品
var product = _unitOfWork.Products.GetById(1);
if (product != null)
{
product.Price = 79.99m;
_unitOfWork.Products.Update(product);
_unitOfWork.Complete();
Console.WriteLine("Updated existing product");
}
// 删除产品
_unitOfWork.Products.Delete(2);
_unitOfWork.Complete();
Console.WriteLine("Deleted product");
}
}
}
5. AppDbContext 类
确保你已经添加了 Microsoft.EntityFrameworkCore 和 Microsoft.EntityFrameworkCore.InMemory 包。这可以通过 NuGet 包管理器或者在命令行中执行以下命令来完成:
dotnet add package Microsoft.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.InMemory
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AppUnitWork
{
public class AppDbContext : DbContext
{
public DbSet<Product> Products { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
// 配置使用内存数据库
optionsBuilder.UseInMemoryDatabase("InMemoryDb");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// 通过种子数据来预填充内存数据库
modelBuilder.Entity<Product>().HasData(
new Product { Id = 1, Name = "Product 1", Price = 10.00m },
new Product { Id = 2, Name = "Product 2", Price = 20.00m }
);
}
}
}
5. 调用
using Microsoft.Extensions.DependencyInjection;
using System;
namespace AppUnitWork
{
internal class Program
{
static void Main(string[] args)
{
// 设置依赖注入
var serviceProvider = new ServiceCollection()
.AddDbContext<AppDbContext>()
.AddScoped<IProductRepository, ProductRepository>()
.AddScoped<IUnitOfWork, UnitOfWork>()
.AddScoped<ProductService>()
.BuildServiceProvider();
using (var scope = serviceProvider.CreateScope())
{
var productService = scope.ServiceProvider.GetRequiredService<ProductService>();
productService.PerformProductOperations();
DisplayAllProducts(scope.ServiceProvider.GetRequiredService<IUnitOfWork>());
}
}
static void DisplayAllProducts(IUnitOfWork unitOfWork)
{
var products = unitOfWork.Products.GetAll();
foreach (var product in products)
{
Console.WriteLine($"Product Id: {product.Id}, Name: {product.Name}, Price: {product.Price}");
}
}
}
}
图片
总结
通过应用工作单元模式,我们能够确保多个数据库操作的事务性,这在进行复杂的业务逻辑和数据操作时尤为重要。本文介绍了工作单元模式的基本概念和实现步骤,附带具体的代码示例,希望对你有所帮助。