Silky微服务框架在线文档Silky微服务框架在线文档
首页
文档
配置
源码解析
博文
github
gitee
首页
文档
配置
源码解析
博文
github
gitee
  • 简介

    • silky 框架介绍
  • 入门

    • 名词解释
    • 快速开始
    • 脚手架
    • 微服务模块化架构的最佳实践 & 约定
    • 示例
  • 主机与模块

    • 主机
    • 网关
    • 模块
    • 插件
  • 网关与 HTTP

    • Swagger 文档
    • 性能分析(MiniProfiler)
    • 跨域(CORS)
    • 审计日志
  • 服务与 RPC

    • 应用服务和服务条目
    • rpc通信
    • websocket通信
    •  服务注册中心
    • 服务治理
  • 数据与缓存

    • EFCore 数据访问
    • 缓存
    • 分布式锁
  • 安全与认证

    • 身份认证与授权
    • 分布式事务
  • 基础设施

    • 依赖注入
    • 对象到对象的映射
    • 参数验证
    • 链路跟踪
    • 日志(Serilog)
    • 健康检查
    • 消息总线(MassTransit)
    • 单元测试与集成测试

概述

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 包获取更多扩展能力。

编辑当前页
Next
缓存