0

マルチデータベース ソリューションがあり、次のように接続文字列をファクトリ関数に渡しています。

container.Register<IDbContextFactory>(
    f => new DynamicDbContextFactory(ClientConfig.GetConnectionString()),
    new PerScopeLifetime());

ClientConfigサブドメインを接続文字列にマップする、アプリの開始時に設定される静的辞書が含まれています。このアプローチがメモリ リークを引き起こしているようです (これが原因でリークが発生していることは 100% 確実ではありませんが、リークは発生しています)。

public class ClientConfig
{
    private static ConcurrentDictionary<string, string> ConnectionStringManager 
    { 
        get;
        set; 
    }

    // etc.
}

私の質問は、チェーンを下に渡すために、各リクエストで簡単に検索できる接続文字列のリストを保持する最良の方法は何ですか。

4

1 に答える 1

0

編集:質問は最初にAutofacでタグ付けされました


Autofacを使用すると、必要なことを行うために辞書などを使用する必要はありません。カスタム パラメータを使用できます。

public class ConnectionStringParameter : Parameter
{
    public override Boolean CanSupplyValue(ParameterInfo pi, 
                                           IComponentContext context, 
                                           out Func<Object> valueProvider)
    {
        valueProvider = null;

        if (pi.ParameterType == typeof(String)
            && String.Equals(pi.Name, "connectionString", 
                             StringComparison.OrdinalIgnoreCase))
        {
            valueProvider = () =>
            {
                // get connectionstring based on HttpContext.Current.Request.Url.Host 
                return String.Empty;
            };
        }

        return valueProvider != null;
    }
}

次に、モジュールを使用してパラメーターを登録します

public class ConnectionStringModule : Autofac.Module
{
    protected override void AttachToComponentRegistration(
        IComponentRegistry componentRegistry, IComponentRegistration registration)
    {
        registration.Preparing += registration_Preparing;
    }

    private void registration_Preparing(Object sender, PreparingEventArgs e)
    {
        Parameter[] parameters = new Parameter[] { new ConnectionStringParameter() }; 
        e.Parameters = e.Parameters.Concat(parameters);
    }
}

を使用してコンテナ内に登録する必要があるモジュール

ContainerBuilder builder = new ContainerBuilder();
builder.RegisterModule(new ConnectionStringModule());

AutofacがconnectionStringStringという名前の型のパラメーターを解決する必要があるたびに、カスタム パラメーターが使用され、必要に応じて接続文字列が取得されます。


ちなみにこのコードサンプルはHttpContext.Current. マルチスレッド プロセスの場合、null が返されることがあります。そのようなものに使用することはお勧めしませんHttpContext.Current。インターフェイスなど、アクセスする代わりに中間クラスを使用できIConnectionstringProviderます。

public interface IConnectionstringProvider
{
    String ConnectionString { get; }
}
public class ConnectionStringProvider : IConnectionstringProvider
{
    public ConnectionStringProvider(Strong host)
    {
        // get connectionstring based on host
        this._connectionString = String.Empty;
    }

    private readonly String _connectionString;

    public String ConnectionString
    {
        get { return this._connectionString; }
    }
}

パラメータ内でvalueProviderを変更する必要があります

valueProvider = () =>
{
    return context.Resolve<IConnectionstringProvider>().ConnectionString; 
};

IConnectionstringProviderそして最後に、リクエストのlifetimescopeの最初にあなたを登録する必要があります:

class Program
{
    static void Main(string[] args)
    {
        ContainerBuilder builder = new ContainerBuilder();
        builder.RegisterModule(new ConnectionStringModule());

        IContainer container = builder.Build();
        container.ChildLifetimeScopeBeginning += container_ChildLifetimeScopeBeginning;
    }

    private static void container_ChildLifetimeScopeBeginning(
        Object sender, LifetimeScopeBeginningEventArgs e)
    {
        String host = HttpContext.Current.Request.Url.Host; 
        ContainerBuilder childLifetimeScopeBuilder = new ContainerBuilder();
        childLifetimeScopeBuilder.RegisterInstance(new ConnectionStringProvider(host))
                                 .As<IConnectionstringProvider>()
                                 .SingleInstance();
        childLifetimeScopeBuilder.Update(e.LifetimeScope.ComponentRegistry);
    }
}

もちろん、それを行う方法はたくさんありますが、あなたにはアイデアがあります

于 2015-04-01T07:53:49.290 に答える