[英]How to register multiple IDbConnectionFactory instances using Funq in ServiceStack.net
您将如何在 Funq 中注册不同的 IDbConnectionFactory 实例,然后直接在您的服务中访问它们? 命名实例是否以某种方式在这里发挥作用?
这是在跨服务使用不同数据库时采取的最佳方法吗?
谢谢!
编辑:
一个例子 ;)。 我可能会离开这里,因为我对 IoC 还很陌生,但是例如,我想注入 2 个独立的数据库连接。 在 ServiceStack 中,这是在 Global.asax 中完成的。
container.Register<IDbConnectionFactory>(c =>
new OrmLiteConnectionFactory(@"Connection String 1", SqlServerOrmLiteDialectProvider.Instance));
container.Register<IDbConnectionFactory>(c =>
new OrmLiteConnectionFactory(@"Connection String 2", SqlServerOrmLiteDialectProvider.Instance));
这两个似乎都注入了honky dory。
然后通过如下方式在服务端自动访问这些:
public IDbConnectionFactory DbFactory { get; set; }
在这种情况下,它似乎给了我第一个注册的。 如何访问服务端的特定服务? 希望这让它更清楚一点。
这是来自 ServiceStack.Examples 的一个完整示例,它仅使用 1 个 IDbConnectionFactory: Movies Rest
我上面的问题仍然有效,但以下内容可能对您有所帮助。
Funq 不支持自动构造函数注入(也称为自动连接),您必须通过构造Func<T>
lambda 表达式来手动执行此操作。 因为您已经在手动进行构造函数注入,所以很容易选择您希望注入到您的服务中的IDbConnectionFactory
。 例子:
IDbConnectionFactory yellowDbConFactory =
new YellowDbConnectionFactory();
IDbConnectionFactory blueDbConFactory =
new BlueDbConnectionFactory();
IDbConnectionFactory purpleDbConFactory =
new PurpleDbConnectionFactory();
container.Register<IService1>(c =>
new Service1Impl(yellowDbConFactory,
c.Resolve<IDep1>());
container.Register<IService2>(c =>
new Service2Impl(blueDbConFactory);
container.Register<IService3>(c =>
new Service3Impl(purpleDbConFactory,
c.Resolve<IDep2>());
当然你也可以使用命名注册,像这样:
container.Register<IDbConnectionFactory>("yellow",
new YellowDbConnectionFactory());
container.Register<IDbConnectionFactory>("blue",
new BlueDbConnectionFactory());
container.Register<IDbConnectionFactory>("purple",
new PurpleDbConnectionFactory());
container.Register<IService1>(c =>
new Service1Impl(
c.Resolve<IDbConnectionFactory>("yellow"),
c.Resolve<IDep1>());
container.Register<IService2>(c =>
new Service2Impl(
c.Resolve<IDbConnectionFactory>("blue"));
container.Register<IService3>(c =>
new Service3Impl(
c.Resolve<IDbConnectionFactory>("purple"),
c.Resolve<IDep2>());
由于缺乏对自动连接的支持,您最终会遇到这些相当尴尬的注册,这很快就会导致您的作文根目录的维护噩梦,但这与您的问题无关;-)
您通常应该尽量避免在您的注册中出现歧义。 在您的情况下,您有一个接口,它可以做两件事(连接到两个数据库)。 除非两个数据库共享完全相同的模型,否则每个数据库都应该拥有自己的接口(如果两个实现不可互换,您将违反Liskov 替换原则):
interface IYellowDbConnectionFactory : IDbConnectionFactory
{
}
interface IPurpleDbConnectionFactory : IDbConnectionFactory
{
}
由于 ServiceStack 的工作方式,您可能需要为每个实现一个实现:
class YellowDbConnectionFactory : OrmLiteConnectionFactory,
IYellowDbConnectionFactory
{
public YellowDbConnectionFactory(string s) : base(s){}
}
class PurpleDbConnectionFactory : OrmLiteConnectionFactory,
IPurpleDbConnectionFactory
{
public YellowDbConnectionFactory(string s) : base(s){}
}
现在您应该更改服务的定义以使用特定接口而不是使用IDbConnectionFactory
:
public class MovieService : RestServiceBase<Movie>
{
private readonly IYellowDbConnectionFactory dbFactory;
public MovieService(IYellowDbConnectionFactory factory)
{
this.dbFactory = factory;
}
}
请注意,此类现在使用构造函数注入而不是属性注入。 你可以让它与属性注入一起工作,但通常最好使用构造函数注入。 这是一个关于它的问题。
使用 Funq,您的配置将如下所示:
container.Register<MovieService>(c =>
new MovieService(
c.Resolve<IYellowDbConnectionFactory>());
这两个新接口和两个类以及对MovieService
更改并没有让您满意,因为 Funq 不支持自动装配。 您将是手动将所有内容连接在一起的人。 然而,当你切换到一个框架,它不支持自动布线,这样的设计允许容器没有问题注入合适的依赖关系,因为没有什么注入讨论。
虽然 Funq 不支持自动布线,但它的ServiceStack实现支持。 最新版本的 ServiceStack 包括 Funq.Container 重载:
container.RegisterAutoWired<T>();
container.RegisterAutoWiredAs<T,TAs>();
container.RegisterAs<T,TAs>();
所以在史蒂文的例子中,你也可以这样做:
container.RegisterAs<YellowDbConnectionFactory,IYellowDbConnectionFactory>();
它会自动为您注册依赖项。
我以为我会在这里花 2 美分,但我意识到这个问题很老了。 我想从 ServiceStack 访问事务数据库和日志数据库,这就是我最终从 AppHostBase Configure() 方法执行此操作的方式:
container.Register<IDbConnectionFactory>(
c => {
OrmLiteConnectionFactory dbFactory = new OrmLiteConnectionFactory(ConfigurationManager.ConnectionStrings["MyTransactionalDB"].ConnectionString, MySqlDialect.Provider);
dbFactory.ConnectionFilter = x => new ProfiledDbConnection(x, Profiler.Current);
dbFactory.RegisterConnection("LoggingDB", ConfigurationManager.ConnectionStrings["MyLoggingDB"].ConnectionString, MySqlDialect.Provider);
return dbFactory;
});
默认情况下,在从工厂打开连接时使用“MyTransactionalDB”,但我可以通过以下方式从服务显式访问日志记录数据库:
using (var db = DbFactory.Open("LoggingDB"))
{
db.Save(...);
}
尝试使用 Repository 模式而不是这个 IoC(这只会使事情不必要地复杂化)。 上面的代码似乎不起作用。 怀疑有什么变了。 我仍然不清楚注册 IDbConnectionFactory 如何神奇地填充 IDbConnection 属性。 希望对此有一些解释。 如果有人确实使用 ServiceStack IoC 容器完成了这项工作..那么我很想看看如何。 更新 SS 文档将非常有益(我很高兴这样做)
您也可以使用字典
使用您的数据库密钥名称创建一个枚举
public enum Database
{
Red,
Blue
}
在 Startup.cs 中,创建一个打开新 SqlConnection 的函数字典,然后将依赖字典作为 Singleton 注入
Dictionary<Database, Func<IDbConnection>> connectionFactory = new()
{
{ Database.Red, () => new SqlConnection(Configuration.GetConnectionString("RedDatabase")) },
{ Database.Blue, () => new SqlConnection(Configuration.GetConnectionString("BlueDatabase")) }
};
services.AddSingleton(connectionFactory);
在您获得实例 od 之后,对对象构造函数的依赖如下:
public class ObjectQueries
{
private readonly IDbConnection _redConnection;
private readonly IDbConnection _blueConnection;
public ObjectQueries(Dictionary<Database, Func<IDbConnection>> connectionFactory)
{
_redConnection = connectionFactory[Database.Red]();
_blueConnection = connectionFactory[Database.Blue]();
}
}
它干净且可读;)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.