我正在通过代码(而不是配置文件)创建多个会话工厂。我遇到的问题是,在第20个会话工厂创建之后,我开始得到一个异常(MappingException),我不知道为什么。
不管是什么顺序,20号以后就坏了。只要会话位于前20个会话中,就可以成功创建会话。
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());
}发布于 2018-07-20 20:19:15
像往常一样,NHibernate的错误消息对任何人都没有帮助。
在我的例子中,我有这个错误:
MappingException消息:唯一后缀100_长度必须少于最多4个字符
经过深入研究,此错误的原因是连接字符串具有错误的服务器地址,然后提供了错误的凭据。
关于你的问题:有20个目标数据库来连接是不寻常的,但这是可以做到的。在下面展示的实现中,我使用了12个会话工厂,但请确保在64位进程空间中运行代码,否则它将很快耗尽32位进程可用的内存。
您需要注意的唯一一件事是,您需要有一个定制的会话工厂构建器,并将其绑定为单例。我的实现的轻量级版本如下所示:
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<ISessionFactoryBuilder>().To<SessionFactoryBuilder>().InSingletonScope().WithConstructorArgument("configurationManager", context => context.Kernel.Get<IConfigurationManager>());当然,你必须在程序启动时的任何地方执行它,或者我们称之为Composition Root。
这里唯一缺少的是IConfigurationManager的明显实现,它只是我对ConfigurationManager的自定义包装器,它被传递给SessionFactoryBuilder的构造函数。
通过这种方式,您可以在应用程序启动时构建您的会话工厂构建器,并且再也不会构建会话工厂构建器(很明显,直到应用程序域重新启动),因此您不会因为有那么多SessionFactories挂起并被创建而发生内存泄漏或OutOfMemory异常。
https://stackoverflow.com/questions/46938003
复制相似问题