我通过代码创建多个会话工厂(不是配置文件) 我遇到的问题是在第20次工厂创建之后,我开始得到一个异常(MappingException),我不知道为什么。
无论顺序如何,20日后都会变坏。只要会话在前20个会话中,就会成功创建会话。
MappingException消息:唯一后缀100_ length必须小于最多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());
}
答案 0 :(得分:3)
像往常一样,NHibernate的错误消息并没有帮助任何人。
就我而言,我遇到了这个错误:
MappingException消息:唯一后缀100_的长度必须小于最大4个字符
经过深入研究,导致此错误的原因是连接字符串的服务器地址错误,然后提供了错误的凭据。
关于您的问题:连接20个目标数据库是不寻常的,但是可以做到。在下面向我展示的实现中,我使用了12个会话工厂,但是请确保您在64位进程空间中运行代码,否则它将很快耗尽32位进程可用的内存。
唯一需要注意的是,您需要具有一个自定义的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<ISessionFactoryBuilder>().To<SessionFactoryBuilder>().InSingletonScope().WithConstructorArgument("configurationManager", context => context.Kernel.Get<IConfigurationManager>());
当然,您必须在程序启动附近或我们称为Composition Root的任何地方执行此操作。
这里唯一缺少的是IConfigurationManager的明显实现,它只是我对ConfigurationManager的自定义包装,并传递给SessionFactoryBuilder
的构造函数。
这样,您可以在应用程序启动时构建会话工厂构建器,而无需再次构建(显然要等到appdomain重新启动之后),因此,不会因为有那么多SessionFactories闲逛而获取内存泄漏或OutOfMemory异常已创建。