在 .netcore 中使用 fluent nhibernate 访问多个数据库

Access multiple databases using fluent nhibernate in .netcore

我是 nHibernate 的新手,正在尝试将它与 .Net 核心一起用于多个 sql 服务器数据库。我浏览了文档并创建了 Isessionfactoty 并在启动时对其进行了配置,但是当我尝试在存储库方法中访问会话对象时,出现错误,因为它只在一个数据库中查找,即 DbConnectionString

我的startup.cs看起来像这样

var sessionFactory = Fluently
                            .Configure()
                            .Database(() =>
                            {
                                return FluentNHibernate.Cfg.Db.MsSqlConfiguration
                                        .MsSql2008
                                        .ShowSql()
                                        .ConnectionString(Configuration.GetConnectionString("DbConnectionString"));
                            })
                            .Database(() =>
                            {
                                return FluentNHibernate.Cfg.Db.MsSqlConfiguration
                                        .MsSql2008
                                        .ShowSql()
                                        .ConnectionString(Configuration.GetConnectionString("AdminDbConnectionString"));
                            })
                            .BuildSessionFactory();

            services.AddSingleton<NHibernate.ISession>(factory => nHIbernateSession.OpenSession());

这是我的存储库 class,我正在从我的控制器中调用它

public class BusinessRepo
    {
        ISession _session;

        public BusinessRepo(ISession session)
        {
            _session = session;
        }

        //This method needs to use DbConnectionString
        public PersonGeo GetPersonById(string personId)
        {
            var value = _session.CreateCriteria<PersonGeo>()
                .Add(Restrictions.Eq("Person_ID", personId))
                .SetCacheable(true)
                .SetCacheMode(CacheMode.Normal)
                .List<PersonGeo>();
            return value.FirstOrDefault();
        }


        //This method needs to used AdminDbConnectionString
        public List<User> GetAllUsers()
        {
            //If I debug the _session and look for connection string it is taking "DbConnectionstring (which is configured first in startup)"
            var result = _session.CreateSQLQuery("SELECT UserID,UserName,Email,IsActive FROM Users").List<User>();
            return result();
        }
    }

这是我的存储库 class,我正在从我的控制器中调用它

  var person = _repo.GetPersonById(personId);
  var allUser = _repo.GetAllUsers();

而且我得到找不到对象名称 "tableName" 因为 _session 对象正在查看其他数据库。有人知道如何实施吗?

将您的启动更改为

    var dbSessionFatory = Fluently
                        .Configure()
                        .Database(() =>
                        {
                            return FluentNHibernate.Cfg.Db.MsSqlConfiguration
                                    .MsSql2008
                                    .ShowSql()
                                    .ConnectionString(Configuration.GetConnectionString("DbConnectionString"));
                        })
                        .BuildSessionFactory();
    var adminDbSessionFactory= Fluently
                        .Configure()
                        .Database(() =>
                        {
                            return FluentNHibernate.Cfg.Db.MsSqlConfiguration
                                    .MsSql2008
                                    .ShowSql()
                                    .ConnectionString(Configuration.GetConnectionString("AdminDbConnectionString"));
                        })
                        .BuildSessionFactory();
       services.AddSingleton<NHibernate.ISession>(factory => dbSessionFatory.OpenSession());
       services.AddSingleton<NHibernate.ISession>(factory => adminDbSessionFactory.OpenSession());

然后将 Sessionfactory 的 IEnumerable 注入 repositoy 方法,并为您需要的数据库使用特定的 sessionfactory。

public class BusinessRepo
    {
        private IEnumerable<ISession> _sessions;

        public BusinessRepo(IEnumerable<ISession> sessions)
        {
            _sessions = sessions;
        }

        //This method needs to use DbConnectionString
        public PersonGeo GetPersonById(string personId)
        {

            var _session = _sessions.Where(a => a.Connection.Database == "DbName").FirstOrDefault();
            var value = _session.CreateCriteria<PersonGeo>()
                .Add(Restrictions.Eq("Person_ID", personId))
                .SetCacheable(true)
                .SetCacheMode(CacheMode.Normal)
                .List<PersonGeo>();
            return value.FirstOrDefault();
        }


        //This method needs to used AdminDbConnectionString
        public List<User> GetAllUsers()
        {

            var _session = _sessions.Where(a => a.Connection.Database == "DbName").FirstOrDefault();
            //If I debug the _session and look for connection string it is taking "DbConnectionstring (which is configured first in startup)"
            var result = _session.CreateSQLQuery("SELECT UserID,UserName,Email,IsActive FROM Users").List<User>();
            return result();
        }
    }

您仍然可以通过创建另一个将数据库名称作为参数和 returns ISession 对象而不是在每个方法中都这样做的方法来重构它

前段时间我遇到了类似的问题,我创建了一个class负责管理多个SessionFactory

在Startup.cs

services.AddSingleton<ISessionSource, SessionSource>();

和class会话源

    public class SessionSource : ISessionSource
    {
        private static readonly object _lockObject = new object();
        private static Dictionary<string, ISessionFactory> _sessionFactories = new Dictionary<string, ISessionFactory>();

        public SessionSource()
        {}

        public ISession GetSession(int csName)
        {
            lock (_lockObject)
            {
                var session = GetSessionFactory(csName).OpenSession();
                return session;
            }
        }

        private FluentConfiguration BaseConfiguration()
        {
            return Fluently.Configure()
                    .Mappings(x => x.FluentMappings.AddFromAssemblyOf<MappingCandidate>())
                    .ExposeConfiguration(cfg =>
                    {
                        new SchemaExport(cfg)
                            .Execute(false, false, false);
                    });
        }

        private Configuration AssembleConfiguration(string connectionString)
        {
            return BaseConfiguration()
                    .Database(() =>
                    {
                        return FluentNHibernate.Cfg.Db.MsSqlConfiguration
                            .MsSql2012
                            .ConnectionString(connectionString);
                    })
                    .BuildConfiguration();
        }

        private ISessionFactory GetSessionFactory(int csName)
        {
            var connectionString = Configuration.GetConnectionString(csName);
            if (_sessionFactories.ContainsKey(connectionString))
            {
                return _sessionFactories[connectionString];
            }
            var sessionFactory = AssembleConfiguration(connectionString).BuildSessionFactory();
            _sessionFactories.Add(connectionString, sessionFactory);
            return sessionFactory;
        }
    }

并在例如控制器中

using (var session = _sessionSource.GetSession(connectionStringName))