c# - NHibernate session 工厂计数限制?

标签 c# nhibernate

我正在通过代码(不是配置文件)创建多个 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/

相关文章:

c# - 更改完成后触发 NHibernate PreUpdateEvent

c# - 如何从位图中获取 Bitsperpixel

c# - 用于检查我的模型属性中的重复项的自定义验证属性未触发

JavaScript 无法在 Asp 上运行。网

c# - 来自不同程序集的 Fluent nhibernate automap 子类

nhibernate - 限制使用 NHibernate QueryOver 进行析取收集

.net - Entity Framework 4与NHibernate

NHibernate - NHibernate 是否识别对象相等并相应地更改保存行为?

c# - 二进制文件的病毒扫描——Blob 与文件

c# - AngularJS 路由问题