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();
}
}
}
我们正在尝试使用 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();
}
}
}