概述
silky 框架集成了基于 Entity Framework Core 的数据访问层(Silky.EntityFrameworkCore 包),提供了仓储模式(Repository Pattern)的数据访问接口,支持多种数据库(SQL Server、MySQL、PostgreSQL、SQLite、Oracle 等),并与 silky 的 DI 容器、分布式事务无缝集成。
主要特性:
- 泛型仓储接口(
IRepository<TEntity>),提供完整 CRUD 操作 - 支持多数据库上下文(多库场景)
- 支持工作单元(Unit of Work)
- 支持 Code First + 数据库迁移
- 与 TCC 分布式事务集成
安装
PM> Install-Package Silky.EntityFrameworkCore -Version 3.9.1
# 额外扩展(软删除、数据范围过滤等)
PM> Install-Package Silky.EntityFrameworkCore.Extras -Version 3.9.1
注册 EFCore 服务
在微服务的 ConfigureService 类中注册数据库服务:
public class ConfigureService : IConfigureService
{
public void ConfigureServices(IServiceCollection services, IConfiguration configuration)
{
services.AddDatabaseAccessor(options =>
{
// 注册主数据库上下文(支持 MySql、SqlServer、PostgreSQL 等)
options.AddDbPool<DefaultDbContext>(DbProvider.MySql);
}, "YourServiceName.Database.Migrations");
}
}
定义 DbContext
继承 AbstractDbContext<TDbContext> 定义数据库上下文:
using Microsoft.EntityFrameworkCore;
using Silky.EntityFrameworkCore.Contexts;
using Silky.EntityFrameworkCore.Locators;
// 注册到主数据库上下文定位器(默认)
public class DefaultDbContext : AbstractDbContext<DefaultDbContext, MasterDbContextLocator>
{
public DefaultDbContext(DbContextOptions<DefaultDbContext> options) : base(options)
{
}
}
定义实体
实体类需要实现 IEntity 接口(或继承 Entity<TKey> 基类):
using Silky.EntityFrameworkCore.Entities;
// 使用基类(推荐),自带 Id 主键和 CreatedTime/UpdatedTime 审计字段
public class Order : Entity<long>
{
public string OrderNo { get; set; }
public decimal Amount { get; set; }
public long UserId { get; set; }
public OrderStatus Status { get; set; }
}
使用仓储进行数据访问
框架会自动将 IRepository<TEntity> 注册到 DI 容器,通过构造注入即可使用:
public class OrderDomainService : IOrderDomainService, IScopedDependency
{
private readonly IRepository<Order> _orderRepository;
public OrderDomainService(IRepository<Order> orderRepository)
{
_orderRepository = orderRepository;
}
// 新增
public async Task<Order> CreateAsync(Order order)
{
return await _orderRepository.InsertNowAsync(order);
}
// 查询单条
public async Task<Order> GetByIdAsync(long id)
{
return await _orderRepository.FindAsync(id);
}
// 条件查询
public async Task<List<Order>> GetByUserIdAsync(long userId)
{
return await _orderRepository
.Where(o => o.UserId == userId && o.Status != OrderStatus.Cancelled)
.OrderByDescending(o => o.Id)
.ToListAsync();
}
// 分页查询
public async Task<(List<Order> Items, int Total)> GetPagedAsync(int pageIndex, int pageSize)
{
var query = _orderRepository.AsQueryable().OrderByDescending(o => o.Id);
var total = await query.CountAsync();
var items = await query.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync();
return (items, total);
}
// 更新(整体更新)
public async Task UpdateAsync(Order order)
{
await _orderRepository.UpdateNowAsync(order);
}
// 删除
public async Task DeleteAsync(long id)
{
await _orderRepository.DeleteNowAsync(id);
}
}
数据库迁移(Code First)
步骤一:创建迁移项目
推荐为每个微服务创建单独的迁移项目(如 YourService.Database.Migrations),添加对 EntityFrameworkCore 项目的引用。
步骤二:添加迁移
# 进入迁移项目目录
cd src/YourService.Database.Migrations
# 添加迁移
dotnet ef migrations add InitialCreate --startup-project ../YourServiceHost
# 更新数据库
dotnet ef database update --startup-project ../YourServiceHost
步骤三:启动时自动迁移(开发环境)
在模块的 Initialize 方法中自动执行迁移:
public class YourServiceModule : SilkyModule
{
public override async Task Initialize(ApplicationContext applicationContext)
{
if (applicationContext.HostEnvironment.IsDevelopment())
{
var dbContext = applicationContext.ServiceProvider
.GetRequiredService<DefaultDbContext>();
await dbContext.Database.MigrateAsync();
}
}
}
多数据库支持
silky EFCore 支持在同一应用中访问多个数据库,通过数据库上下文定位器区分。
定义第二个数据库定位器
// 定义数据库定位器
public class SlaveDbContextLocator : IDbContextLocator
{
}
// 定义对应的 DbContext
public class SlaveDbContext : AbstractDbContext<SlaveDbContext, SlaveDbContextLocator>
{
public SlaveDbContext(DbContextOptions<SlaveDbContext> options) : base(options)
{
}
}
// 注册
services.AddDatabaseAccessor(options =>
{
options.AddDbPool<DefaultDbContext>(DbProvider.MySql);
options.AddDbPool<SlaveDbContext, SlaveDbContextLocator>(DbProvider.MySql);
});
使用指定数据库的仓储
// 注入特定数据库上下文的仓储
private readonly IRepository<Order, SlaveDbContextLocator> _slaveOrderRepository;
配置数据库连接字符串
在 appsettings.yaml 中配置数据库连接字符串:
connectionStrings:
# 默认主数据库
default: Server=127.0.0.1;Port=3306;Database=order_db;Uid=root;Pwd=qwe!P4ss;
# 多数据库(key 对应定位器类名的小写)
slave: Server=127.0.0.1;Port=3306;Database=order_slave_db;Uid=root;Pwd=qwe!P4ss;
提示
Silky.EntityFrameworkCore 源码参考了 Furion 框架的设计,功能十分丰富,包括软删除、数据范围过滤、审计日志、实体变更监听等高级特性,可参考 Silky.EntityFrameworkCore.Extras 包获取更多扩展能力。
