一起聊聊 C# 中的工作单元模式

开发 前端
我们能够确保多个数据库操作的事务性,这在进行复杂的业务逻辑和数据操作时尤为重要。本文介绍了工作单元模式的基本概念和实现步骤,附带具体的代码示例,希望对你有所帮助。

工作单元(Unit of Work, UoW)模式是一种用于处理事务性工作的方法,特别适用于需要对数据库进行多次操作时。它的主要目的是将多个数据库操作封装在一个事务中,确保所有操作能整体成功或者整体失败,从而保证数据的一致性。

本文将详细介绍如何在 C# 中实现工作单元模式,并提供完整的代码注释。

工作单元模式的关键概念

  1. 工作单元(Unit of Work):一个类,它封装了一个业务事务的多个操作,并记录对这些操作的更改。
  2. 仓储(Repository):一个类,它管理实体的持久化,并通常与工作单元合作。
  3. 事务管理:确保多次数据库操作要么全部成功,要么全部回滚。

实现步骤

下面是实现工作单元模式的步骤:

  1. 定义实体类。
  2. 定义仓储接口和实现。
  3. 定义工作单元接口和实现。
  4. 使用工作单元及其仓储。

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}");
            }
        }
    }
}

图片图片

总结

通过应用工作单元模式,我们能够确保多个数据库操作的事务性,这在进行复杂的业务逻辑和数据操作时尤为重要。本文介绍了工作单元模式的基本概念和实现步骤,附带具体的代码示例,希望对你有所帮助。


责任编辑:武晓燕 来源: 技术老小子
相关推荐

2023-10-10 08:00:07

2024-07-10 08:31:59

C#特性代码

2024-08-26 08:34:47

AES加密算法

2022-03-15 20:18:35

单元测试工具

2012-10-08 11:18:38

企业应用架构工作单元模式

2023-08-07 08:04:05

动态抽象工厂模式

2024-05-29 13:18:12

线程Thread​方式

2024-08-30 11:00:22

2022-12-06 08:12:11

Java关键字

2024-01-01 08:19:32

模式History前端

2023-10-26 08:38:43

SQL排名平分分区

2024-11-15 16:52:23

C#栈边界栈基址

2022-10-08 00:00:05

SQL机制结构

2023-04-26 07:30:00

promptUI非结构化

2024-08-07 10:37:24

2023-08-04 08:20:56

DockerfileDocker工具

2023-08-10 08:28:46

网络编程通信

2022-05-24 08:21:16

数据安全API

2023-09-10 21:42:31

2023-09-21 08:16:56

JDK 21向量计算计算
点赞
收藏

51CTO技术栈公众号