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.
}

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

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必须解析String名为connectionString类型的参数时,它将使用自定义参数并根据您的需要获取您的连接字符串。


顺便说一下,这个代码示例使用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; }
    }
}

在您的Parameter中,您必须通过以下方式更改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);
    }
}

当然有很多方法可以做到,但你有想法

于 2015-04-01T07:53:49.290 回答