首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >NHibernate会话工厂计数限制?

NHibernate会话工厂计数限制?
EN

Stack Overflow用户
提问于 2017-10-26 00:53:12
回答 1查看 552关注 0票数 2

我正在通过代码(而不是配置文件)创建多个会话工厂。我遇到的问题是,在第20个会话工厂创建之后,我开始得到一个异常(MappingException),我不知道为什么。

不管是什么顺序,20号以后就坏了。只要会话位于前20个会话中,就可以成功创建会话。

MappingException消息:唯一后缀100_长度必须少于最多4个字符

任何帮助都是非常感谢的。

代码语言:javascript
复制
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());
    }
EN

回答 1

Stack Overflow用户

发布于 2018-07-20 20:19:15

像往常一样,NHibernate的错误消息对任何人都没有帮助。

在我的例子中,我有这个错误:

MappingException消息:唯一后缀100_长度必须少于最多4个字符

经过深入研究,此错误的原因是连接字符串具有错误的服务器地址,然后提供了错误的凭据。

关于你的问题:有20个目标数据库来连接是不寻常的,但这是可以做到的。在下面展示的实现中,我使用了12个会话工厂,但请确保在64位进程空间中运行代码,否则它将很快耗尽32位进程可用的内存。

您需要注意的唯一一件事是,您需要有一个定制的会话工厂构建器,并将其绑定为单例。我的实现的轻量级版本如下所示:

代码语言:javascript
复制
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绑定为:

代码语言:javascript
复制
Bind<ISessionFactoryBuilder>().To<SessionFactoryBuilder>().InSingletonScope().WithConstructorArgument("configurationManager", context => context.Kernel.Get<IConfigurationManager>());

当然,你必须在程序启动时的任何地方执行它,或者我们称之为Composition Root

这里唯一缺少的是IConfigurationManager的明显实现,它只是我对ConfigurationManager的自定义包装器,它被传递给SessionFactoryBuilder的构造函数。

通过这种方式,您可以在应用程序启动时构建您的会话工厂构建器,并且再也不会构建会话工厂构建器(很明显,直到应用程序域重新启动),因此您不会因为有那么多SessionFactories挂起并被创建而发生内存泄漏或OutOfMemory异常。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46938003

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档