NHibernate创建配置提供程序

时间:2020-09-13 21:03:56

标签: c# nhibernate azure-sql-database

我们正在尝试使用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类

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:'无法实例化连接 提供者:Project.connection.AzureSQLDatabase'TypeLoadException: 无法加载类型Project.connection.AzureSQLDatabase。可能 原因:未指定程序集名称。

您知道我们缺少什么/正在跳过吗?

2 个答案:

答案 0 :(得分:0)

错误消息很清楚。您指定的类型名称不带程序集名称。

public static void StatusChecker()
{ 
    Console.WriteLine("Your health is " + Items.health);
    Console.WriteLine("Your energy is " + Items.energy);
}

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

自定义IConnectionProvider实现的类型。例如。 如果提供程序是内置的,则为full.classname.of.ConnectionProvider NHibernate,或者 full.classname.of.ConnectionProvider,程序集(如果使用) NHibernate中未包含的IConnectionProvider的实现。 默认值为NHibernate.Connection.DriverConnectionProvider。

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

答案 1 :(得分:0)

我找到了更好的解决方案。设置属性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();
        }
    }
}