CSharp: Unit of Work Pattern in donet core 6
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Geovin.Du.DuUnitOfWork.Domain { /// <summary> /// /// </summary> public abstract class Entity { /// <summary> /// /// </summary> public int Id { get; init; } } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Geovin.Du.DuUnitOfWork.Domain { /// <summary> /// 工作单元模式 Unit of Work Pattern /// </summary> public class Order : Entity { /// <summary> /// /// </summary> public string Description { get; set; } = string.Empty; /// <summary> /// /// </summary> public string DeliveryAddress { get; set; } = string.Empty; /// <summary> /// /// </summary> public decimal Price { get; set; } } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Geovin.Du.DuUnitOfWork.Domain { /// <summary> /// 工作单元模式 Unit of Work Pattern /// </summary> public class Customer : Entity { /// <summary> /// /// </summary> public string FirstName { get; set; } = string.Empty; /// <summary> /// /// </summary> public string LastName { get; set; } = string.Empty; } } using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Text; using System.Threading.Tasks; using Geovin.Du.DuUnitOfWork.Domain; namespace Geovin.Du.DuUnitOfWork.DuExample.Infrastructure.Repositories.Contracts { public interface IRepositoryDu<T> where T : Entity { T Add(T entity); IEnumerable<T> GetAll(); IEnumerable<T> Get(Expression<Func<T, bool>> predicate); T GetById(int id); void Delete(T entity); } } using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Text; using System.Threading.Tasks; using Geovin.Du.DuUnitOfWork.DuExample.Infrastructure.Repositories.Contracts; using Geovin.Du.DuUnitOfWork.Domain; namespace Geovin.Du.DuUnitOfWork.DuExample.Infrastructure.Repositories { /// <summary> /// /// </summary> /// <typeparam name="T"></typeparam> public class RepositoryDu<T> : IRepositoryDu<T> where T : Entity { protected OrderManagementContextDu _context; public RepositoryDu(OrderManagementContextDu context) { _context = context; } public virtual T Add(T entity) => _context .Add(entity) .Entity; public virtual IEnumerable<T> GetAll() => _context.Set<T>().ToList(); public virtual IEnumerable<T> Get(Expression<Func<T, bool>> predicate) => _context.Set<T>() .AsQueryable() .Where(predicate) .ToList(); public virtual T GetById(int id) { var entity = _context.Find<T>(id); return entity ?? throw new ArgumentException($"Entity with {id} doesn't exists"); } public virtual void Delete(T entity) => _context.Remove(entity); } } using Geovin.Du.DuUnitOfWork.DuExample.Infrastructure.Repositories.Contracts; using Geovin.Du.DuUnitOfWork.Domain; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Geovin.Du.DuUnitOfWork.DuExample.Infrastructure { /// <summary> /// /// </summary> public interface IUnitOfWorkDu { IRepositoryDu<Customer> CustomerRepository { get; } IRepositoryDu<Order> OrderRepository { get; } void SaveChanges(); } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Geovin.Du.DuUnitOfWork.Domain; namespace Geovin.Du.DuUnitOfWork.DuExample.Infrastructure { public class OrderManagementContextDu : DbContext { public DbSet<Customer> Customers => Set<Customer>(); public DbSet<Order> Orders => Set<Order>(); protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => optionsBuilder.UseSqlite("Data Source=storage1.db"); } } using Geovin.Du.DuUnitOfWork.DuExample.Infrastructure.Repositories; using Geovin.Du.DuUnitOfWork.DuExample.Infrastructure.Repositories.Contracts; using Geovin.Du.DuUnitOfWork.Domain; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Geovin.Du.DuUnitOfWork.DuExample.Infrastructure { /// <summary> /// /// </summary> public class UnitOfWorkDu : IUnitOfWorkDu { private readonly OrderManagementContextDu _context; private IRepositoryDu<Customer>? _customerRepository; private IRepositoryDu<Order>? _orderRepository; public UnitOfWorkDu(OrderManagementContextDu context) { _context = context; } public IRepositoryDu<Customer> CustomerRepository { get { if (_customerRepository == null) { _customerRepository = new RepositoryDu<Customer>(_context); } return _customerRepository; } } public IRepositoryDu<Order> OrderRepository { get { if (_orderRepository == null) { _orderRepository = new RepositoryDu<Order>(_context); } return _orderRepository; } } public void SaveChanges() => _context.SaveChanges(); } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Geovin.Du.DuUnitOfWork.Domain; using Geovin.Du.DuUnitOfWork.DuExample.Infrastructure; namespace Geovin.Du.DuUnitOfWork.DuExample.Controllers { /// <summary> /// /// </summary> public class CustomerControllerDu { private readonly IUnitOfWorkDu _unitOfWork; public CustomerControllerDu(IUnitOfWorkDu unitOfWork) { _unitOfWork = unitOfWork; } public IEnumerable<Customer> GetAll() => _unitOfWork.CustomerRepository.GetAll(); } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Geovin.Du.DuUnitOfWork.Domain; using Geovin.Du.DuUnitOfWork.DuExample.Infrastructure; namespace Geovin.Du.DuUnitOfWork.DuExample.Controllers { /// <summary> /// /// </summary> public class OrderControllerDu { private readonly IUnitOfWorkDu _unitOfWork; public OrderControllerDu(IUnitOfWorkDu unitOfWork) { _unitOfWork = unitOfWork; } public Order Create(int id, string description, string deliveryAddress, decimal price) { // ID is usually auto-generated by database. var newOrder = new Order { Id = id, Description = description, DeliveryAddress = deliveryAddress, Price = price, }; newOrder = _unitOfWork.OrderRepository.Add(newOrder); // _unitOfWork.CustomerRepository.Add(new Customer() { Id = 33 }); // In this example we work only with order repository, // but it would be possible to create/update different entities by using // different repositories and save all changes via unit of work instance. _unitOfWork.SaveChanges(); return newOrder; } public IEnumerable<Order> GetAll() => _unitOfWork.OrderRepository.GetAll(); } }
/// <summary> /// /// </summary> public static class DuExampleExecutor { /// <summary> /// /// </summary> public static void Execute() { ConsoleExtension.WriteSeparator("工作单元模式 Unit of Work Pattern- demo"); InitializeDatabase(); using var context = new OrderManagementContextDu(); var unitOfWork = new UnitOfWorkDu(context); var customerController = new CustomerControllerDu(unitOfWork); var orderController = new OrderControllerDu(unitOfWork); ShowAllCustomers(); ShowAllOrders(); CreateNewOrder(); ShowAllOrders(); void ShowAllCustomers() { Console.WriteLine("显示所有客户..."); foreach (var customer in customerController.GetAll()) { Console.WriteLine($"{customer.FirstName} {customer.LastName}"); } } void ShowAllOrders() { Console.WriteLine("\n显示所有订单..."); foreach (var order in orderController.GetAll()) { Console.WriteLine($"{order.Description} 价格为: {order.Price:C}"); } } void CreateNewOrder() { Console.WriteLine("\n创建新订单..."); orderController.Create(3, "游船 5", "北京 3", 9800); } } /// <summary> /// /// </summary> private static void InitializeDatabase() { using var context = new OrderManagementContextDu(); context.Database.EnsureDeleted(); context.Database.EnsureCreated(); var du = new Customer { Id = 1, FirstName = "Du", LastName = "Geovin" }; var tu = new Customer { Id = 2, FirstName = "Tu", LastName = "Juwen" }; var camera = new Order { Id = 1, Description = "摄像机", DeliveryAddress = "深圳 1", Price = 880 }; var phone = new Order { Id = 2, Description = "手机", DeliveryAddress = "上海 2", Price = 210 }; var unitOfWork = new UnitOfWorkDu(context); unitOfWork.CustomerRepository.Add(du); unitOfWork.CustomerRepository.Add(tu); unitOfWork.OrderRepository.Add(camera); unitOfWork.OrderRepository.Add(phone); unitOfWork.SaveChanges(); } } }
调用:
Geovin.Du.DuUnitOfWork.DuExample.DuExampleExecutor.Execute();
输出:
工作单元模式 Unit of Work Pattern- demo -------------------------------------------------- 显示所有客户... Du Geovin Tu Juwen 显示所有订单... 摄像机 价格为: ¥880.00 手机 价格为: ¥210.00 创建新订单... 显示所有订单... 摄像机 价格为: ¥880.00 手机 价格为: ¥210.00 游船 5 价格为: ¥9800.00
哲学管理(学)人生, 文学艺术生活, 自动(计算机学)物理(学)工作, 生物(学)化学逆境, 历史(学)测绘(学)时间, 经济(学)数学金钱(理财), 心理(学)医学情绪, 诗词美容情感, 美学建筑(学)家园, 解构建构(分析)整合学习, 智商情商(IQ、EQ)运筹(学)生存.---Geovin Du(涂聚文)