簡體   English   中英

如何在 ServiceStack.net 中使用 Funq 注冊多個 IDbConnectionFactory 實例

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM