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

  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章