手把手教你:在.Net 8的ABP框架中,同时集成FreeSql和SqlSugar(附完整代码)
在ABP框架中同时集成FreeSql与SqlSugar的深度实践指南
当企业级应用需要同时兼顾开发效率与性能优化时,多ORM混搭架构正成为.NET技术栈的新趋势。本文将深入探讨如何在ABP VNext框架中实现FreeSql与SqlSugar的双引擎集成,通过模块化设计让两种ORM各展所长。
1. 混合ORM架构的设计价值
在微服务与模块化开发盛行的当下,单一ORM很难满足所有业务场景的需求。FreeSql以零配置、强类型著称,特别适合快速迭代的业务模块;而SqlSugar凭借卓越的读写性能,往往是高频交易场景的首选。ABP框架的依赖注入系统为这种混合架构提供了天然支持。
实际项目中最常见的混用场景包括:
- 历史模块使用SqlSugar需要保留
- 报表模块依赖FreeSql的复杂查询能力
- 需要对比两种ORM在真实业务中的表现
- 渐进式迁移过程中的过渡方案
提示:混合架构会增加一定复杂度,建议在项目规模达到20个以上领域模型时考虑采用
2. 环境准备与基础配置
2.1 创建ABP VNext项目
使用ABP CLI创建模块化解决方案:
abp new Acme.BookStore -t app -u mvc --mobile none --database-provider mysql2.2 添加ORM包引用
在领域层和基础设施层添加NuGet包:
<!-- FreeSql全家桶 --> <PackageReference Include="FreeSql.Provider.MySql" Version="3.2.800" /> <PackageReference Include="FreeSql.DbContext" Version="3.2.800" /> <!-- SqlSugar核心包 --> <PackageReference Include="SqlSugarCore" Version="5.1.4.59" />2.3 数据库连接配置
在appsettings.json中配置多数据库连接:
"ConnectionStrings": { "Default": "Server=localhost;Port=3306;Database=BookStore;Uid=root;Pwd=123456;", "ReadReplica": "Server=replica1;Port=3306;Database=BookStore;Uid=readonly;Pwd=123456;" }3. 模块化集成方案
3.1 FreeSql模块实现
创建FreeSqlModule.cs实现ABP模块:
[DependsOn(typeof(AbpDddModule))] public class FreeSqlModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { var configuration = context.Services.GetConfiguration(); var freeSql = new FreeSqlBuilder() .UseConnectionString(DataType.MySql, configuration.GetConnectionString("Default")) .UseAutoSyncStructure(false) // 禁用自动迁移 .UseMonitorCommand(cmd => Logger.LogDebug($"FreeSql执行:{cmd.CommandText}")) .Build(); context.Services.AddSingleton<IFreeSql>(freeSql); context.Services.AddFreeRepository(); } }3.2 SqlSugar模块实现
创建SqlSugarModule.cs配置作用域:
[DependsOn(typeof(AbpDddModule))] public class SqlSugarModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddSingleton<ISqlSugarClient>(provider => { var config = provider.GetRequiredService<IConfiguration>(); return new SqlSugarScope(new ConnectionConfig() { DbType = DbType.MySql, ConnectionString = config.GetConnectionString("Default"), IsAutoCloseConnection = true }, db => { db.Aop.OnLogExecuting = (sql, pars) => { Logger.LogInformation($"SqlSugar执行:{sql}"); }; }); }); } }4. 双ORM仓储模式设计
4.1 基础仓储抽象类
// FreeSql仓储基类 public abstract class FreesqlRepository<TEntity> : DomainService where TEntity : class, IEntity { protected IFreeSql FreeSql => LazyServiceProvider.LazyGetRequiredService<IFreeSql>(); public virtual async Task<TEntity> GetAsync(long id) { return await FreeSql.Select<TEntity>() .Where(x => x.Id == id) .ToOneAsync(); } } // SqlSugar仓储基类 public abstract class SqlSugarRepository<TEntity> : DomainService where TEntity : class, new() { protected ISqlSugarClient Db => LazyServiceProvider.LazyGetRequiredService<ISqlSugarClient>(); public virtual async Task<TEntity> GetAsync(dynamic id) { return await Db.Queryable<TEntity>() .InSingleAsync(id); } }4.2 业务仓储实现示例
public class BookRepository : SqlSugarRepository<Book>, ITransientDependency { public async Task<List<Book>> GetHotBooksAsync(int count) { return await Db.Queryable<Book>() .OrderBy(b => b.Sales, OrderByType.Desc) .Take(count) .ToListAsync(); } } public class AuthorRepository : FreesqlRepository<Author>, ITransientDependency { public async Task<List<Author>> GetPopularAuthorsAsync() { return await FreeSql.Select<Author>() .Include(a => a.Books) .Where(a => a.Fans > 1000) .ToListAsync(); } }5. 应用服务层的最佳实践
5.1 多ORM服务注入模式
public class BookAppService : ApplicationService { private readonly BookRepository _sqlSugarRepo; private readonly AuthorRepository _freeSqlRepo; public BookAppService( BookRepository sqlSugarRepo, AuthorRepository freeSqlRepo) { _sqlSugarRepo = sqlSugarRepo; _freeSqlRepo = freeSqlRepo; } public async Task<BookWithAuthorDto> GetBookDetailsAsync(long id) { var book = await _sqlSugarRepo.GetAsync(id); var author = await _freeSqlRepo.GetAsync(book.AuthorId); return new BookWithAuthorDto { Book = book, Author = author }; } }5.2 事务跨ORM处理方案
public async Task CreateOrderAsync(OrderCreateDto input) { using (var uow = UnitOfWorkManager.Begin( requiresNew: true, isTransactional: true)) { try { // FreeSql操作 await _freeSqlRepo.InsertAsync(input.Books); // SqlSugar操作 await _sqlSugarRepo.AddAsync(input.Order); await uow.CompleteAsync(); } catch { await uow.RollbackAsync(); throw; } } }6. 性能优化与调试技巧
6.1 连接池配置建议
| ORM类型 | 参数 | 推荐值 | 说明 |
|---|---|---|---|
| FreeSql | PoolSize | 100 | 连接池大小 |
| SqlSugar | ConnectionPoolSize | 50 | 连接池实例数 |
| 通用 | IdleTimeout | 300 | 空闲连接超时(秒) |
6.2 日志监控配置
在appsettings.json中添加:
"Logging": { "LogLevel": { "FreeSql": "Debug", "SqlSugar": "Information" } }6.3 常见问题排查
- 依赖冲突:检查Newtonsoft.Json版本是否兼容
- 事务失效:确保UnitOfWork作用域正确
- 性能下降:监控连接泄露情况
- 迁移差异:禁用自动迁移功能
在ABP框架中同时使用两种ORM,就像为项目配备了瑞士军刀和手术刀——前者应对日常开发游刃有余,后者则在性能关键路径上精准高效。经过多个项目的实践验证,这种架构特别适合需要兼顾开发速度与运行效率的中大型商业系统。
