How to extend NHibernate to support more databases?
.net, c#, nhibernate
Solution
NHibernate is designed to operate with dialects of SQL and not ad hoc query languages. This will be very tricky to accomplish. But to answer your question, you need:
- An ADO.NET provider for your database (this would be a separate question).
A Driver class (derived from NHibernate's DriverBase). Here is one I have written in the past (somewhat anonymised):
public sealed class XxxClientDriver : DriverBase
{
public override IDbConnection CreateConnection()
{
return XxxClientFactory.Instance.CreateConnection();
}
public override IDbCommand CreateCommand()
{
return XxxClientFactory.Instance.CreateCommand();
}
public override bool UseNamedPrefixInSql
{
get { return true; }
}
public override bool UseNamedPrefixInParameter
{
get { return true; }
}
public override string NamedPrefix
{
get { return "@"; }
}
}
Possibly (definitely in your case) a Dialect, deriving from NHibernate's Dialect class, that defines classes to render each particular syntax element in your language (note, though, that this is still SQL-orientated, which is I suspect where you are going to fall down here). An example in my case:
public sealed class XxxDialect : Dialect
{
public override JoinFragment CreateOuterJoinFragment()
{
return new XxxJoinFragment();
}
}
As many non-standard syntax elements (compared to normal SQL) as your language has. Again, an example from my case:
public sealed class XxxJoinFragment : JoinFragment
{
private readonly SqlStringBuilder _afterFrom;
public XxxJoinFragment()
{
_afterFrom = new SqlStringBuilder();
}
private SqlStringBuilder AfterFrom
{
get { return _afterFrom; }
}
public override SqlString ToFromFragmentString
{
get { return _afterFrom.ToSqlString(); }
}
public override SqlString ToWhereFragmentString
{
get { return SqlString.Empty; }
}
public override void AddJoin(string tableName, string alias,
string[] fkColumns, string[] pkColumns,
JoinType joinType)
{
AddCrossJoin(tableName, alias);
}
public override void AddJoin(string tableName, string alias,
string[] fkColumns, string[] pkColumns,
JoinType joinType, string on)
{
AddJoin(tableName, alias, fkColumns, pkColumns, joinType);
}
public override void AddCrossJoin(string tableName, string alias)
{
AfterFrom.Add(", ").Add(tableName).Add(" ").Add(alias);
}
public override void AddJoins(SqlString fromFragment, SqlString whereFragment)
{
AddFromFragmentString(fromFragment);
}
public override bool AddCondition(string condition)
{
return true;
}
public override bool AddCondition(SqlString condition)
{
return true;
}
public override void AddFromFragmentString(SqlString fromFragmentString)
{
AfterFrom.Add(fromFragmentString);
}
}
As you can see, in my case (a SQL-based query language with implicit join conditions) this was not too hard. But in your case I suspect you're going to be up against it. Good luck!
Problem
If I needed to get NHibernate to support more databases (not included in the list of supported: https://www.hibernate.org/361.html), assuming that database can be accessed using it's built-in query language,but not SQL (example: http://kx.com/Products/kdb+.php)... - How will I be able to get NHibernate to work with these databases?