我们有一个多数据库解决方案,并将连接字符串传递给一个工厂函数,如下所示:
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必须解析名为connectionString的String
类型的参数时,它将使用自定义参数并根据您的需要获取连接字符串。
顺便说一下,这个代码示例使用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);
}
}
当然,有很多方法可以做到这一点,但您有