[英]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.