我们正在尝试使用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。可能 原因:未指定程序集名称。
您知道我们缺少什么/正在跳过吗?
答案 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();
}
}
}