Web API、Light Inject和将静态字典传递到数据层



我们有一个多数据库解决方案,并将连接字符串传递给一个工厂函数,如下所示:

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

ClientConfig包含一个静态字典,该字典在应用程序启动时填充,将子域映射到连接字符串。这种方法似乎会导致内存泄漏(不能100%确定是否会导致泄漏,但确实存在泄漏)。

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

我的问题是,在MVC中,什么是保存连接字符串列表的最佳方式,可以在每个请求上轻松查找这些连接字符串,以便将其传递到链中。

编辑:问题最初用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

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);
    }
}

当然,有很多方法可以做到这一点,但您有

的想法

相关内容

  • 没有找到相关文章

最新更新