我正在通过代码(不是配置文件)创建多个 session 工厂 我遇到的问题是,在创建第 20 个 session 工厂之后,我开始收到异常 (MappingException),但我不知道为什么。
无论顺序如何,20号之后就坏了。只要是前20个 session 就创建成功。
MappingException 消息:唯一后缀 100_ 长度必须小于最多 4 个字符
感谢任何帮助。
public static void AddPortfolioToConnectionstrings(string portfolio, string
connectionString)
{
var configuration = new Configuration()
.Configure()
.SessionFactoryName(portfolio)
.SetProperty("connection.connection_string", connectionString);
...
_portfolios.Add(portfolio, configuration.BuildSessionFactory());
}
最佳答案
像往常一样,NHibernate 的错误消息对任何人都没有帮助。
就我而言,我遇到了这个错误:
MappingException message: Unique suffix 100_ length must be less than maximum 4 characters
经过深入研究,此错误的原因是连接字符串的服务器地址错误,然后提供了错误的凭据。
关于您的问题:连接 20 个目标数据库是不寻常的,但这是可以做到的。在我下面向您展示的实现中,我使用 12 个 session 工厂,但请确保在 64 位进程空间中运行代码,否则它将很快耗尽 32 位进程的可用内存。
您需要注意的唯一一件事是您需要有一个绑定(bind)为单例的自定义 session 工厂构建器。我的实现的轻量级版本如下所示:
public interface ISessionFactoryBuilder
{
IDictionary<string, ISessionFactory> SessionFactories { get; }
}
public IDictionary<string, ISessionFactory> SessionFactories { get; private set; }
private readonly IConfigurationManager _configurationManager;
public SessionFactoryBuilder(IConfigurationManager configurationManager)
{
this._configurationManager = configurationManager;
this.SessionFactories = this.BuildSessionFactories();
}
private IDictionary<string, ISessionFactory> BuildSessionFactories()
{
var sessionFactories = new Dictionary<string, ISessionFactory>(StringComparer.InvariantCultureIgnoreCase);
var connectionStrings = this._configurationManager.GetConnectionStrings();
if (connectionStrings.Count == 0)
throw new ConfigurationErrorsException("No connection descriptions can be found!");
foreach (ConnectionStringSettings item in connectionStrings)
if (item.Name != "LocalSqlServer" && item.Name != "OraAspNetConString")
sessionFactories.Add(item.Name, this.InitializeSessionFactory(item.ConnectionString, item.ProviderName));
return sessionFactories;
}
private class Connectiontypes
{
public string Db_type { get; set; }
public FluentConfiguration Configuration { get; set; }
}
private ISessionFactory InitializeSessionFactory(string connectionString = "", string providerName = "")
{
Trace.WriteLine($"{connectionString}");
List<SessionFactoryBuilder.Connectiontypes> conntypes = new List<SessionFactoryBuilder.Connectiontypes> {
new SessionFactoryBuilder.Connectiontypes
{
Db_type = "System.Data.SqlClient",
Configuration = Fluently.Configure().Database(MsSqlConfiguration.MsSql2005.ConnectionString(connectionString).ShowSql()
.Dialect<XMsSql2005Dialect>()) },
new SessionFactoryBuilder.Connectiontypes
{
Db_type = "System.Data.OracleDataClient",
Configuration = Fluently.Configure().Database(OracleDataClientConfiguration.Oracle10
.ConnectionString(connectionString).Provider<NHibernate.Connection.DriverConnectionProvider>()
.Driver<NHibernate.Driver.OracleManagedDataClientDriver>()
.Dialect<XOracle10gDialect>().ShowSql())
},
new SessionFactoryBuilder.Connectiontypes
{
Db_type = "System.Data.MySQLDataClient", Configuration = Fluently.Configure()
.Database(MySQLConfiguration.Standard.ConnectionString(connectionString).ShowSql())
}
};
FluentConfiguration fluentConfiguration = conntypes.Find(x => x.Db_type == providerName).Configuration;
fluentConfiguration.ExposeConfiguration(x =>
{
x.SetProperty("command_timeout", "120");
});
#if DEBUG
fluentConfiguration.ExposeConfiguration(x =>
{
x.SetInterceptor(new SqlStatementInterceptor());
});
#endif
var mappings = fluentConfiguration.Mappings(m =>
{
m.FluentMappings.AddFromAssemblyOf<UsersMap>();
});
var config = mappings.BuildConfiguration();
foreach (PersistentClass persistentClass in config.ClassMappings)
{
persistentClass.DynamicUpdate = true;
}
var sessionFactory = mappings
#if DEBUG
.Diagnostics(d => d.Enable(true))
.Diagnostics(d => d.OutputToConsole())
#endif
.BuildSessionFactory();
return sessionFactory;
}
public void Dispose()
{
if (this.SessionFactories.Count > 0)
{
foreach (var item in this.SessionFactories)
{
item.Value.Close();
item.Value.Dispose();
}
this.SessionFactories = null;
}
}
}
然后我将其与 NInject 绑定(bind)为:
Bind<ISessionFactoryBuilder>().To<SessionFactoryBuilder>().InSingletonScope().WithConstructorArgument("configurationManager", context => context.Kernel.Get<IConfigurationManager>());
当然,您必须在程序启动附近的任何地方执行此操作,或者我们称之为 Composition Root .
这里唯一缺少的是 IConfigurationManager 的明显实现,它只是我对 ConfigurationManager 的自定义包装器。 ,它被传递到 SessionFactoryBuilder
的构造函数。
通过这种方式,您可以在应用程序启动时构建 session 工厂构建器,并且不再构建(显然直到应用程序域重新启动左右),因此您不会因为有那么多 SessionFactories 闲置并获取而出现内存泄漏或 OutOfMemory 异常创建。
关于c# - NHibernate session 工厂计数限制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46938003/