第十四章:仓储模式与依赖注入
目录
14.1 仓储模式概述
14.1.1 什么是仓储模式
仓储模式(Repository Pattern)是一种数据访问模式,它在数据访问层和业务逻辑层之间建立一个抽象层。
核心概念:
// 传统方式:业务逻辑直接依赖数据库操作
public class StudentService
{
private SqlSugarClient _db;
public List<Student> GetStudents()
{
return _db.Queryable<Student>().ToList(); // 直接依赖SqlSugar
}
}
// 仓储模式:业务逻辑依赖仓储接口
public class StudentService
{
private IStudentRepository _repository;
public List<Student> GetStudents()
{
return _repository.GetAll(); // 依赖抽象接口
}
}
14.1.2 仓储模式的优势
- 解耦:业务逻辑与数据访问分离
- 可测试:便于单元测试(Mock)
- 可维护:集中管理数据访问逻辑
- 可复用:避免重复代码
- 灵活性:易于更换数据访问技术
14.2 基础仓储实现
14.2.1 定义仓储接口
// 基础仓储接口
public interface IRepository<T> where T : class, new()
{
// 查询
T GetById(object id);
List<T> GetList();
List<T> GetList(Expression<Func<T, bool>> whereExpression);
// 分页
PageResult<T> GetPageList(int pageIndex, int pageSize);
PageResult<T> GetPageList(Expression<Func<T, bool>> whereExpression, int pageIndex, int pageSize);
// 插入
int Insert(T entity);
int InsertRange(List<T> entities);
// 更新
bool Update(T entity);
bool Update(Expression<Func<T, T>> columns, Expression<Func<T, bool>> whereExpression);
// 删除
bool Delete(T entity);
bool Delete(object id);
bool Delete(Expression<Func<T, bool>> whereExpression);
// 聚合
int Count(Expression<Func<T, bool>> whereExpression);
bool Any(Expression<Func<T, bool>> whereExpression);
// 事务
void BeginTran();
void CommitTran();
void RollbackTran();
}
// 学生仓储接口(特定实体)
public interface IStudentRepository : IRepository<Student>
{
// 特定业务方法
List<Student> GetStudentsByClass(int classId);
List<Student> GetStudentsByAge(int minAge, int maxAge);
Student GetStudentByEmail(string email);
}
14.2.2 实现基础仓储
// 基础仓储实现
public class Repository<T> : IRepository<T> where T : class, new()
{
protected readonly ISqlSugarClient _db;
public Repository(ISqlSugarClient db)
{
_db = db;
}
public virtual T GetById(object id)
{
return _db.Queryable<T>().InSingle(id);
}
public virtual List<T> GetList()
{
return _db.Queryable<T>().ToList();
}
public virtual List<T> GetList(Expression<Func<T, bool>> whereExpression)
{
return _db.Queryable<T>().Where(whereExpression).ToList();
}
public virtual PageResult<T> GetPageList(int pageIndex, int pageSize)
{
int totalCount = 0;
var list = _db.Queryable<T>()
.ToPageList(pageIndex, pageSize, ref totalCount);
return new PageResult<T>
{
PageIndex = pageIndex,
PageSize = pageSize,
TotalCount = totalCount,
TotalPages = (int)Math.Ceiling(totalCount / (double)pageSize),
Items = list
};
}
public virtual PageResult<T> GetPageList(
Expression<Func<T, bool>> whereExpression,
int pageIndex,
int pageSize)
{
int totalCount = 0;
var list = _db.Queryable<T>()
.Where(whereExpression)
.ToPageList(pageIndex, pageSize, ref totalCount);
return new PageResult<T>
{
PageIndex = pageIndex,
PageSize = pageSize,
TotalCount = totalCount,
TotalPages = (int)Math.Ceiling(totalCount / (double)pageSize),
Items = list
};
}
public virtual int Insert(T entity)
{
return _db.Insertable(entity).ExecuteReturnIdentity();
}
public virtual int InsertRange(List<T> entities)
{
return _db.Insertable(entities).ExecuteCommand();
}
public virtual bool Update(T entity)
{
return _db.Updateable(entity).ExecuteCommandHasChange();
}
public virtual bool Update(
Expression<Func<T, T>> columns,
Expression<Func<T, bool>> whereExpression)
{
return _db.Updateable<T>()
.SetColumns(columns)
.Where(whereExpression)
.ExecuteCommandHasChange();
}
public virtual bool Delete(T entity)
{
return _db.Deleteable(entity).ExecuteCommandHasChange();
}
public virtual bool Delete(object id)
{
return _db.Deleteable<T>().In(id).ExecuteCommandHasChange();
}
public virtual bool Delete(Expression<Func<T, bool>> whereExpression)
{
return _db.Deleteable<T>()
.Where(whereExpression)
.ExecuteCommandHasChange();
}
public virtual int Count(Expression<Func<T, bool>> whereExpression)
{
return _db.Queryable<T>().Where(whereExpression).Count();
}
public virtual bool Any(Expression<Func<T, bool>> whereExpression)
{
return _db.Queryable<T>().Where(whereExpression).Any();
}
public virtual void BeginTran()
{
_db.BeginTran();
}
public virtual void CommitTran()
{
_db.CommitTran();
}
public virtual void RollbackTran()
{
_db.RollbackTran();
}
}
// 学生仓储实现
public class StudentRepository : Repository<Student>, IStudentRepository
{
public StudentRepository(ISqlSugarClient db) : base(db)
{
}
public List<Student> GetStudentsByClass(int classId)
{
return _db.Queryable<Student>()
.Where(s => s.ClassId == classId)
.ToList();
}
public List<Student> GetStudentsByAge(int minAge, int maxAge)
{
return _db.Queryable<Student>()
.Where(s => s.Age >= minAge && s.Age <= maxAge)
.ToList();
}
public Student GetStudentByEmail(string email)
{
return _db.Queryable<Student>()
.First(s => s.Email == email);
}
}
14.3 泛型仓储
增强的泛型仓储实现:
// 异步仓储接口
public interface IRepositoryAsync<T> where T : class, new()
{
Task<T> GetByIdAsync(object id);
Task<List<T>> GetListAsync();
Task<List<T>> GetListAsync(Expression<Func<T, bool>> whereExpression);
Task<PageResult<T>> GetPageListAsync(int pageIndex, int pageSize);
Task<int> InsertAsync(T entity);
Task<int> InsertRangeAsync(List<T> entities);
Task<bool> UpdateAsync(T entity);
Task<bool> DeleteAsync(object id);
Task<int> CountAsync(Expression<Func<T, bool>> whereExpression);
Task<bool> AnyAsync(Expression<Func<T, bool>> whereExpression);
}
// 异步仓储实现
public class RepositoryAsync<T> : IRepositoryAsync<T> where T : class, new()
{
protected readonly ISqlSugarClient _db;
public RepositoryAsync(ISqlSugarClient db)
{
_db = db;
}
public virtual async Task<T> GetByIdAsync(object id)
{
return await _db.Queryable<T>().InSingleAsync(id);
}
public virtual async Task<List<T>> GetListAsync()
{
return await _db.Queryable<T>().ToListAsync();
}
public virtual async Task<List<T>> GetListAsync(Expression<Func<T, bool>> whereExpression)
{
return await _db.Queryable<T>().Where(whereExpression).ToListAsync();
}
public virtual async Task<PageResult<T>> GetPageListAsync(int pageIndex, int pageSize)
{
RefAsync<int> totalCount = 0;
var list = await _db.Queryable<T>()
.ToPageListAsync(pageIndex, pageSize, totalCount);
return new PageResult<T>
{
PageIndex = pageIndex,
PageSize = pageSize,
TotalCount = totalCount,
TotalPages = (int)Math.Ceiling(totalCount / (double)pageSize),
Items = list
};
}
public virtual async Task<int> InsertAsync(T entity)
{
return await _db.Insertable(entity).ExecuteReturnIdentityAsync();
}
public virtual async Task<int> InsertRangeAsync(List<T> entities)
{
return await _db.Insertable(entities).ExecuteCommandAsync();
}
public virtual async Task<bool> UpdateAsync(T entity)
{
return await _db.Updateable(entity).ExecuteCommandHasChangeAsync();
}
public virtual async Task<bool> DeleteAsync(object id)
{
return await _db.Deleteable<T>().In(id).ExecuteCommandHasChangeAsync();
}
public virtual async Task<int> CountAsync(Expression<Func<T, bool>> whereExpression)
{
return await _db.Queryable<T>().Where(whereExpression).CountAsync();
}
public virtual async Task<bool> AnyAsync(Expression<Func<T, bool>> whereExpression)
{
return await _db.Queryable<T>().Where(whereExpression).AnyAsync();
}
}
// 完整功能的泛型仓储
public class FullRepository<T> : RepositoryAsync<T>, IRepository<T>, IRepositoryAsync<T>
where T : class, new()
{
public FullRepository(ISqlSugarClient db) : base(db)
{
}
// 实现同步方法
public T GetById(object id)
{
return _db.Queryable<T>().InSingle(id);
}
public List<T> GetList()
{
return _db.Queryable<T>().ToList();
}
public List<T> GetList(Expression<Func<T, bool>> whereExpression)
{
return _db.Queryable<T>().Where(whereExpression).ToList();
}
public PageResult<T> GetPageList(int pageIndex, int pageSize)
{
int totalCount = 0;
var list = _db.Queryable<T>()
.ToPageList(pageIndex, pageSize, ref totalCount);
return new PageResult<T>
{
PageIndex = pageIndex,
PageSize = pageSize,
TotalCount = totalCount,
Items = list
};
}
public PageResult<T> GetPageList(
Expression<Func<T, bool>> whereExpression,
int pageIndex,
int pageSize)
{
int totalCount = 0;
var list = _db.Queryable<T>()
.Where(whereExpression)
.ToPageList(pageIndex, pageSize, ref totalCount);
return new PageResult<T>
{
PageIndex = pageIndex,
PageSize = pageSize,
TotalCount = totalCount,
Items = list
};
}
public int Insert(T entity)
{
return _db.Insertable(entity).ExecuteReturnIdentity();
}
public int InsertRange(List<T> entities)
{
return _db.Insertable(entities).ExecuteCommand();
}
public bool Update(T entity)
{
return _db.Updateable(entity).ExecuteCommandHasChange();
}
public bool Update(
Expression<Func<T, T>> columns,
Expression<Func<T, bool>> whereExpression)
{
return _db.Updateable<T>()
.SetColumns(columns)
.Where(whereExpression)
.ExecuteCommandHasChange();
}
public bool Delete(T entity)
{
return _db.Deleteable(entity).ExecuteCommandHasChange();
}
public bool Delete(object id)
{
return _db.Deleteable<T>().In(id).ExecuteCommandHasChange();
}
public bool Delete(Expression<Func<T, bool>> whereExpression)
{
return _db.Deleteable<T>()
.Where(whereExpression)
.ExecuteCommandHasChange();
}
public int Count(Expression<Func<T, bool>> whereExpression)
{
return _db.Queryable<T>().Where(whereExpression).Count();
}
public bool Any(Expression<Func<T, bool>> whereExpression)
{
return _db.Queryable<T>().Where(whereExpression).Any();
}
public void BeginTran()
{
_db.BeginTran();
}
public void CommitTran()
{
_db.CommitTran();
}
public void RollbackTran()
{
_db.RollbackTran();
}
}
14.4 工作单元模式
// 工作单元接口
public interface IUnitOfWork : IDisposable
{
ISqlSugarClient Db { get; }
void BeginTran();
void CommitTran();
void RollbackTran();
IRepository<T> GetRepository<T>() where T : class, new();
}
// 工作单元实现
public class UnitOfWork : IUnitOfWork
{
private readonly ISqlSugarClient _db;
private readonly Dictionary<Type, object> _repositories;
private bool _disposed = false;
public UnitOfWork(ISqlSugarClient db)
{
_db = db;
_repositories = new Dictionary<Type, object>();
}
public ISqlSugarClient Db => _db;
public void BeginTran()
{
_db.BeginTran();
}
public void CommitTran()
{
_db.CommitTran();
}
public void RollbackTran()
{
_db.RollbackTran();
}
public IRepository<T> GetRepository<T>() where T : class, new()
{
var type = typeof(T);
if (!_repositories.ContainsKey(type))
{
_repositories[type] = new Repository<T>(_db);
}
return (IRepository<T>)_repositories[type];
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
_repositories.Clear();
}
_disposed = true;
}
}
}
// 使用工作单元
public class OrderService
{
private readonly IUnitOfWork _unitOfWork;
public OrderService(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public bool CreateOrder(Order order, List<OrderItem> items)
{
try
{
_unitOfWork.BeginTran();
// 创建订单
var orderRepo = _unitOfWork.GetRepository<Order>();
var orderId = orderRepo.Insert(order);
// 添加订单项
var itemRepo = _unitOfWork.GetRepository<OrderItem>();
foreach (var item in items)
{
item.OrderId = orderId;
itemRepo.Insert(item);
}
// 更新库存
var productRepo = _unitOfWork.GetRepository<Product>();
foreach (var item in items)
{
productRepo.Update(
p => new Product { Stock = p.Stock - item.Quantity },
p => p.Id == item.ProductId);
}
_unitOfWork.CommitTran();
return true;
}
catch
{
_unitOfWork.RollbackTran();
return false;
}
}
}
14.5 依赖注入集成
14.5.1 ASP.NET Core集成
// Startup.cs 或 Program.cs
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// 注册SqlSugarClient
services.AddSingleton<ISqlSugarClient>(provider =>
{
return new SqlSugarClient(new ConnectionConfig
{
ConnectionString = Configuration.GetConnectionString("DefaultConnection"),
DbType = DbType.SqlServer,
IsAutoCloseConnection = true,
InitKeyType = InitKeyType.Attribute
});
});
// 注册仓储
services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
services.AddScoped<IStudentRepository, StudentRepository>();
services.AddScoped<ITeacherRepository, TeacherRepository>();
// 注册工作单元
services.AddScoped<IUnitOfWork, UnitOfWork>();
// 注册服务
services.AddScoped<IStudentService, StudentService>();
services.AddScoped<ITeacherService, TeacherService>();
services.AddControllers();
}
}
// 使用 SqlSugarScope 支持多租户
public void ConfigureServicesWithScope(IServiceCollection services)
{
services.AddSingleton<SqlSugarScope>(provider =>
{
return new SqlSugarScope(new ConnectionConfig
{
ConnectionString = Configuration.GetConnectionString("DefaultConnection"),
DbType = DbType.SqlServer,
IsAutoCloseConnection = true
});
});
// 注册为ISqlSugarClient
services.AddScoped<ISqlSugarClient>(provider =>
{
return provider.GetRequiredService<SqlSugarScope>();
});
}
// 控制器中使用
[ApiController]
[Route("api/[controller]")]
public class StudentController : ControllerBase
{
private readonly IStudentRepository _repository;
private readonly IStudentService _service;
public StudentController(
IStudentRepository repository,
IStudentService service)
{
_repository = repository;
_service = service;
}
[HttpGet]
public ActionResult<List<Student>> GetAll()
{
var students = _repository.GetList();
return Ok(students);
}
[HttpGet("{id}")]
public ActionResult<Student> Get(int id)
{
var student = _repository.GetById(id);
if (student == null)
return NotFound();
return Ok(student);
}
[HttpPost]
public ActionResult<int> Create([FromBody] Student student)
{
var id = _repository.Insert(student);
return Ok(id);
}
}
14.5.2 Autofac集成
public class AutofacModule : Module
{
protected override void Load(ContainerBuilder builder)
{
// 注册SqlSugarClient
builder.Register(c =>
{
return new SqlSugarClient(new ConnectionConfig
{
ConnectionString = "Server=.;Database=test;User ID=sa;Password=123;",
DbType = DbType.SqlServer,
IsAutoCloseConnection = true
});
}).As<ISqlSugarClient>().SingleInstance();
// 注册泛型仓储
builder.RegisterGeneric(typeof(Repository<>))
.As(typeof(IRepository<>))
.InstancePerLifetimeScope();
// 注册具体仓储
builder.RegisterType<StudentRepository>()
.As<IStudentRepository>()
.InstancePerLifetimeScope();
// 注册工作单元
builder.RegisterType<UnitOfWork>()
.As<IUnitOfWork>()
.InstancePerLifetimeScope();
// 自动注册所有服务
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
.Where(t => t.Name.EndsWith("Service"))
.AsImplementedInterfaces()
.InstancePerLifetimeScope();
}
}
// Program.cs
public class Program
{
public static void Main(string[] args)
{
var host = Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureContainer<ContainerBuilder>(builder =>
{
builder.RegisterModule<AutofacModule>();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.Build();
host.Run();
}
}
14.6 服务层设计
// 服务层接口
public interface IStudentService
{
StudentDto GetById(int id);
List<StudentDto> GetAll();
PageResult<StudentDto> GetPageList(int pageIndex, int pageSize);
int Create(CreateStudentDto dto);
bool Update(int id, UpdateStudentDto dto);
bool Delete(int id);
}
// 服务层实现
public class StudentService : IStudentService
{
private readonly IStudentRepository _repository;
private readonly IMapper _mapper;
private readonly ILogger<StudentService> _logger;
public StudentService(
IStudentRepository repository,
IMapper mapper,
ILogger<StudentService> logger)
{
_repository = repository;
_mapper = mapper;
_logger = logger;
}
public StudentDto GetById(int id)
{
_logger.LogInformation($"获取学生信息: {id}");
var student = _repository.GetById(id);
if (student == null)
{
throw new NotFoundException($"学生不存在: {id}");
}
return _mapper.Map<StudentDto>(student);
}
public List<StudentDto> GetAll()
{
var students = _repository.GetList();
return _mapper.Map<List<StudentDto>>(students);
}
public PageResult<StudentDto> GetPageList(int pageIndex, int pageSize)
{
var result = _repository.GetPageList(pageIndex, pageSize);
return new PageResult<StudentDto>
{
PageIndex = result.PageIndex,
PageSize = result.PageSize,
TotalCount = result.TotalCount,
TotalPages = result.TotalPages,
Items = _mapper.Map<List<StudentDto>>(result.Items)
};
}
public int Create(CreateStudentDto dto)
{
_logger.LogInformation($"创建学生: {dto.Name}");
// 验证
if (string.IsNullOrEmpty(dto.Name))
{
throw new ValidationException("姓名不能为空");
}
// 检查邮箱是否已存在
if (_repository.Any(s => s.Email == dto.Email))
{
throw new ValidationException("邮箱已存在");
}
var student = _mapper.Map<Student>(dto);
student.CreateTime = DateTime.Now;
return _repository.Insert(student);
}
public bool Update(int id, UpdateStudentDto dto)
{
_logger.LogInformation($"更新学生: {id}");
var student = _repository.GetById(id);
if (student == null)
{
throw new NotFoundException($"学生不存在: {id}");
}
_mapper.Map(dto, student);
student.UpdateTime = DateTime.Now;
return _repository.Update(student);
}
public bool Delete(int id)
{
_logger.LogInformation($"删除学生: {id}");
var student = _repository.GetById(id);
if (student == null)
{
throw new NotFoundException($"学生不存在: {id}");
}
return _repository.Delete(id);
}
}
// 复杂业务服务
public class OrderService
{
private readonly IUnitOfWork _unitOfWork;
private readonly IMapper _mapper;
private readonly ILogger<OrderService> _logger;
public OrderService(
IUnitOfWork unitOfWork,
IMapper mapper,
ILogger<OrderService> logger)
{
_unitOfWork = unitOfWork;
_mapper = mapper;
_logger = logger;
}
public int CreateOrder(CreateOrderDto dto)
{
_logger.LogInformation($"创建订单: 用户{dto.UserId}");
try
{
_unitOfWork.BeginTran();
// 1. 创建订单
var order = _mapper.Map<Order>(dto);
order.OrderNo = GenerateOrderNo();
order.CreateTime = DateTime.Now;
order.Status = OrderStatus.Pending;
var orderRepo = _unitOfWork.GetRepository<Order>();
var orderId = orderRepo.Insert(order);
// 2. 创建订单项
var itemRepo = _unitOfWork.GetRepository<OrderItem>();
decimal totalAmount = 0;
foreach (var itemDto in dto.Items)
{
// 检查库存
var productRepo = _unitOfWork.GetRepository<Product>();
var product = productRepo.GetById(itemDto.ProductId);
if (product == null)
{
throw new ValidationException($"商品不存在: {itemDto.ProductId}");
}
if (product.Stock < itemDto.Quantity)
{
throw new ValidationException($"库存不足: {product.Name}");
}
// 创建订单项
var item = new OrderItem
{
OrderId = orderId,
ProductId = itemDto.ProductId,
ProductName = product.Name,
Price = product.Price,
Quantity = itemDto.Quantity,
Amount = product.Price * itemDto.Quantity
};
itemRepo.Insert(item);
totalAmount += item.Amount;
// 减库存
product.Stock -= itemDto.Quantity;
productRepo.Update(product);
}
// 3. 更新订单总金额
order.TotalAmount = totalAmount;
orderRepo.Update(order);
_unitOfWork.CommitTran();
_logger.LogInformation($"订单创建成功: {orderId}");
return orderId;
}
catch (Exception ex)
{
_unitOfWork.RollbackTran();
_logger.LogError(ex, "创建订单失败");
throw;
}
}
private string GenerateOrderNo()
{
return $"ORD{DateTime.Now:yyyyMMddHHmmss}{new Random().Next(1000, 9999)}";
}
}
14.7 架构模式
14.7.1 三层架构
项目结构:
├── MyProject.Models # 实体层
│ ├── Student.cs
│ └── Teacher.cs
├── MyProject.Repository # 仓储层
│ ├── IRepository.cs
│ ├── Repository.cs
│ ├── IStudentRepository.cs
│ └── StudentRepository.cs
├── MyProject.Service # 服务层
│ ├── IStudentService.cs
│ └── StudentService.cs
└── MyProject.Api # 表示层
└── Controllers
└── StudentController.cs
14.7.2 DDD架构
// 领域模型(Domain Model)
namespace MyProject.Domain.Models
{
public class Student : AggregateRoot
{
public int Id { get; private set; }
public string Name { get; private set; }
public int Age { get; private set; }
// 领域行为
public void ChangeName(string newName)
{
if (string.IsNullOrEmpty(newName))
throw new DomainException("姓名不能为空");
Name = newName;
AddDomainEvent(new StudentNameChangedEvent(Id, newName));
}
}
}
// 领域仓储接口
namespace MyProject.Domain.Repositories
{
public interface IStudentRepository
{
Student GetById(int id);
void Add(Student student);
void Update(Student student);
void Remove(Student student);
}
}
// 基础设施层实现
namespace MyProject.Infrastructure.Repositories
{
public class StudentRepository : IStudentRepository
{
private readonly ISqlSugarClient _db;
public StudentRepository(ISqlSugarClient db)
{
_db = db;
}
public Student GetById(int id)
{
var entity = _db.Queryable<StudentEntity>()
.First(s => s.Id == id);
return MapToDomain(entity);
}
public void Add(Student student)
{
var entity = MapToEntity(student);
_db.Insertable(entity).ExecuteCommand();
}
public void Update(Student student)
{
var entity = MapToEntity(student);
_db.Updateable(entity).ExecuteCommand();
}
public void Remove(Student student)
{
_db.Deleteable<StudentEntity>()
.Where(s => s.Id == student.Id)
.ExecuteCommand();
}
private Student MapToDomain(StudentEntity entity)
{
// 映射到领域模型
return new Student(entity.Id, entity.Name, entity.Age);
}
private StudentEntity MapToEntity(Student domain)
{
// 映射到持久化实体
return new StudentEntity
{
Id = domain.Id,
Name = domain.Name,
Age = domain.Age
};
}
}
}
14.7.3 CQRS模式
// 命令(Command)
public class CreateStudentCommand
{
public string Name { get; set; }
public int Age { get; set; }
public string Email { get; set; }
}
// 命令处理器
public class CreateStudentCommandHandler
{
private readonly IStudentRepository _repository;
public CreateStudentCommandHandler(IStudentRepository repository)
{
_repository = repository;
}
public int Handle(CreateStudentCommand command)
{
var student = new Student
{
Name = command.Name,
Age = command.Age,
Email = command.Email,
CreateTime = DateTime.Now
};
return _repository.Insert(student);
}
}
// 查询(Query)
public class GetStudentQuery
{
public int Id { get; set; }
}
// 查询处理器
public class GetStudentQueryHandler
{
private readonly ISqlSugarClient _db;
public GetStudentQueryHandler(ISqlSugarClient db)
{
_db = db;
}
public StudentDto Handle(GetStudentQuery query)
{
return _db.Queryable<Student>()
.Where(s => s.Id == query.Id)
.Select(s => new StudentDto
{
Id = s.Id,
Name = s.Name,
Age = s.Age,
Email = s.Email
})
.First();
}
}
// 使用MediatR实现CQRS
public class StudentController : ControllerBase
{
private readonly IMediator _mediator;
public StudentController(IMediator mediator)
{
_mediator = mediator;
}
[HttpPost]
public async Task<ActionResult<int>> Create([FromBody] CreateStudentCommand command)
{
var id = await _mediator.Send(command);
return Ok(id);
}
[HttpGet("{id}")]
public async Task<ActionResult<StudentDto>> Get(int id)
{
var query = new GetStudentQuery { Id = id };
var result = await _mediator.Send(query);
return Ok(result);
}
}
14.8 本章小结
本章详细介绍了仓储模式与依赖注入:
- 仓储模式:理解了仓储模式的概念、优势和实现方法
- 基础仓储:实现了完整的CRUD操作仓储
- 泛型仓储:创建了可复用的泛型仓储,支持同步和异步操作
- 工作单元:实现了工作单元模式,管理事务和多个仓储
- 依赖注入:掌握了与ASP.NET Core和Autofac的集成
- 服务层:设计了完整的服务层,封装业务逻辑
- 架构模式:学习了三层架构、DDD和CQRS等架构模式
通过本章的学习,您应该能够构建结构清晰、易于维护的企业级应用程序。在下一章(最后一章)中,我们将学习SqlSugar的高级特性与最佳实践,并对整个教程进行总结。