如何为多数据库场景注入多个SqlKata QueryFactory实例?
解决多个SqlKata QueryFactory实例的注入问题
当需要注入多个对应不同数据库连接的QueryFactory时,有两种实用方案可以实现:
方案一:使用Keyed服务(.NET 6+原生支持)
.NET 6及以上版本的DI容器支持Keyed服务,可以给同类型的服务实例标记不同的键,注入时通过键区分目标实例。
1. 注册带键的QueryFactory
在Program.cs中分别注册两个带标识键的QueryFactory:
// 注册第一个数据库的QueryFactory,标记键为"Db1" builder.Services.AddKeyedTransient<QueryFactory>("Db1", (sp, key) => { var connection = new SqlConnection(CONST.Db1ConnectionString); var compiler = new SqlServerCompiler(); return new QueryFactory(connection, compiler); }); // 注册第二个数据库的QueryFactory,标记键为"Db2" builder.Services.AddKeyedTransient<QueryFactory>("Db2", (sp, key) => { var connection = new SqlConnection(CONST.Db2ConnectionString); var compiler = new SqlServerCompiler(); return new QueryFactory(connection, compiler); });
2. 在控制器中指定注入实例
使用[FromKeyedServices]特性明确要注入的服务键:
using SqlKata; using SqlKata.Execution; using Microsoft.Extensions.DependencyInjection; public class HomeController { private readonly QueryFactory _db1; private readonly QueryFactory _db2; public HomeController( [FromKeyedServices("Db1")] QueryFactory db1, [FromKeyedServices("Db2")] QueryFactory db2 ) { _db1 = db1; _db2 = db2; } public IActionResult Index() { // 查询第一个数据库的Books表 var db1Books = _db1.Query("Books").Where("IsPublished", true).Get<Book>(); // 查询第二个数据库的Products表 var db2Products = _db2.Query("Products").Where("IsActive", true).Get<Product>(); return Ok(new { Db1Books = db1Books, Db2Products = db2Products }); } }
方案二:自定义包装类(兼容所有.NET版本)
如果项目版本低于.NET 6,或者更倾向于类型安全的注入方式,可以为每个QueryFactory创建专属的包装类。
1. 创建数据库专属包装类
using SqlKata.Execution; using System.Data.SqlClient; // 第一个数据库的专属包装类 public class Db1QueryFactory : QueryFactory { public Db1QueryFactory(SqlConnection connection, SqlServerCompiler compiler) : base(connection, compiler) { } } // 第二个数据库的专属包装类 public class Db2QueryFactory : QueryFactory { public Db2QueryFactory(SqlConnection connection, SqlServerCompiler compiler) : base(connection, compiler) { } }
2. 注册包装类
在Program.cs中注册这两个自定义包装类:
builder.Services.AddTransient<Db1QueryFactory>(sp => { var connection = new SqlConnection(CONST.Db1ConnectionString); var compiler = new SqlServerCompiler(); return new Db1QueryFactory(connection, compiler); }); builder.Services.AddTransient<Db2QueryFactory>(sp => { var connection = new SqlConnection(CONST.Db2ConnectionString); var compiler = new SqlServerCompiler(); return new Db2QueryFactory(connection, compiler); });
3. 直接注入控制器
using SqlKata.Execution; public class HomeController { private readonly Db1QueryFactory _db1; private readonly Db2QueryFactory _db2; public HomeController(Db1QueryFactory db1, Db2QueryFactory db2) { _db1 = db1; _db2 = db2; } public IActionResult Index() { var db1Books = _db1.Query("Books").Where("IsPublished", true).Get<Book>(); var db2Products = _db2.Query("Products").Where("IsActive", true).Get<Product>(); return Ok(new { Db1Books = db1Books, Db2Products = db2Products }); } }
两种方案各有优势:Keyed服务实现更轻量,无需额外定义类;自定义包装类类型区分更明确,避免注入时因键名拼写出错。可根据项目版本和实际需求选择。
内容的提问来源于stack exchange,提问作者Magus
相关产品推荐
相关产品推荐

