NHibernate 创建配置提供程序

NHibernate create configuration provider

我们正在尝试使用 nhibernate 实现云数据库解决方案。我们正在使用 Azure SQL 数据库,我们在设置连接时遇到了麻烦。由于连接字符串中不允许使用 Authentication 关键字,因此创建连接的唯一方法是提供访问令牌。此 属性 在 nhibernate 上不可用。我们被建议创建我们自己的连接提供商以实现这一目标。我们的连接提供的是:

using Project.dataaccessobjects;
using Project.security;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using NHibernate.Connection;
using System;
using System.Data.Common;
using System.Data.SqlClient;
using System.Threading.Tasks;
namespace Project.connection
{
    public partial class AzureSQLDatabase : DriverConnectionProvider
    {
        private string strSQLServer{ get; set; }
        private string strDatabase { get; set; }
        private string strTenantId { get; set; }
        private string strClientId { get; set; }
        private string strPassword { get; set; }
        public AzureSQLDatabase() : base()
        {
            strSQLServer = AzureKeyVaultDAO.getInstance().get("SQLServer");
            strDatabase = AzureKeyVaultDAO.getInstance().get("Database");
            strTenantId = AzureKeyVaultDAO.getInstance().get("TenantId");
            strClientId = AzureKeyVaultDAO.getInstance().get("ClientId");
            strPassword = AzureKeyVaultDAO.getInstance().get("Password");
        }
        private string accessToken()
        {
            const string ResourceUrl = "https://database.windows.net/";
            string AuthorityUrl = $"https://login.microsoftonline.com/{strTenantId}";
            AuthenticationContext objAuthenticationContext;
            Task<AuthenticationResult> objAuthenticationResult;
            ClientCredential objCredentials;
            objCredentials = new ClientCredential(strClientId, SecureText.getInstance().decrypt(strPassword));
            objAuthenticationContext = new AuthenticationContext(AuthorityUrl);
            objAuthenticationResult = objAuthenticationContext.AcquireTokenAsync(ResourceUrl, objCredentials);
            return objAuthenticationResult.Result.AccessToken;
        }
        public override DbConnection GetConnection(string connectionString)
        {
            DbConnection objConnection = new SqlConnection();
            try
            {
                objConnection.ConnectionString = connectionString;
                ((SqlConnection) objConnection).AccessToken = accessToken();
                objConnection.Open();
            }
            catch (Exception)
            {
                objConnection.Dispose();
                throw;
            }
            return objConnection;
        }
    }
}

接下来就是我们的HibernateUtil class

using Project.dataaccessobjects;
using Project.entities;
using NHibernate;
using NHibernate.Cfg;
using System.Collections.Generic;
namespace Project.hibernate
{
    public class HibernateUtil
    {
        private static ISessionFactory _sessionFactory;
        private static ISessionFactory SessionFactory
        {
            get
            {
                if (_sessionFactory == null)
                {
                    Configuration objConfiguration = new Configuration();
                    objConfiguration.SetProperties(properties());
                    objConfiguration.AddAssembly(typeof(Entity/Beam/Domain).Assembly);
                    _sessionFactory = objConfiguration.BuildSessionFactory();
                }
                return _sessionFactory;
            }
        }
        private static Dictionary<string, string> properties()
        {
            Dictionary<string, string> obj = new Dictionary<string, string>();
            obj.Add("connection.provider", "Project.connection.AzureSQLDatabase");
            obj.Add("connection.connection_string", $"Server = tcp:{AzureKeyVaultDAO.getInstance().get("SQLServer")},1433; Initial Catalog = {AzureKeyVaultDAO.getInstance().get("Database")}; Persist Security Info = False; MultipleActiveResultSets = False; Encrypt = True; TrustServerCertificate = False");
            obj.Add("dialect", "NHibernate.Dialect.MsSqlAzure2008Dialect");
            obj.Add("show_sql", "true");
            return obj;
        }
        public static ISession OpenSession()
        {
            return SessionFactory.OpenSession();
        }
    }
}

在 objConfiguration.BuildSessionFactory() 处,我们得到以下异常:

NHibernate.HibernateException: 'Could not instantiate connection provider: Project.connection.AzureSQLDatabase' TypeLoadException: Could not load type Project.connection.AzureSQLDatabase. Possible cause: no assembly name specified.

你知道我们是什么吗missing/skipping?

错误信息很清楚。您指定了一个没有程序集名称的类型名称。

 obj.Add("connection.provider", "Project.connection.AzureSQLDatabase");

这还不足以让 NHibernate 找到类型。要加载类型,您必须知道它在哪个程序集中。来自文档:

The type of a custom IConnectionProvider implementation. eg. full.classname.of.ConnectionProvider if the Provider is built into NHibernate, or full.classname.of.ConnectionProvider, assembly if using an implementation of IConnectionProvider not included in NHibernate. The default is NHibernate.Connection.DriverConnectionProvider.

https://nhibernate.info/doc/nhibernate-reference/session-configuration.html

我找到了更好的解决方案。设置 属性 Environment.Hbm2ddlKeyWords, "none" 允许我执行 BuildSessionFactory 并打开设置 SessionFactory.OpenSession() 的连接。

namespace ExceptionsDB.hibernate
{
    public class HibernateUtil
    {
        private static ISessionFactory _sessionFactory;
        private static ISessionFactory SessionFactory
        {
            get
            {
                if (_sessionFactory == null)
                {
                    Configuration objConfiguration = new Configuration();
                    objConfiguration.SetProperties(properties());
                    //Add all Entities
                    objConfiguration.AddAssembly(typeof(Entity/Bean/Domain).Assembly);
                    _sessionFactory = objConfiguration.BuildSessionFactory();
                }
                return _sessionFactory;
            }
        }
        private static Dictionary<string, string> properties()
        {
            Dictionary<string, string> obj = new Dictionary<string, string>();
            obj.Add("dialect", "NHibernate.Dialect.MsSqlAzure2008Dialect");
            obj.Add(Environment.Hbm2ddlKeyWords, "none");
            obj.Add("show_sql", "true");
            return obj;
        }
        public static ISession OpenSession()
        {
            //return SessionFactory.OpenSession(ADO.NET Connection); obsolete
            return SessionFactory.WithOptions().Connection(ADO.NET Connection).OpenSession();
        }
    }
}