Due to the fact that the error is already indicating that NHibernate does not support that feature. I would create a named query and solve the equation within a query. I have tested it with MySQL (using a common username and password comparison as example) and the following statement returns the desired row (password is a BINARY(32) field):
SELECT * FROM `user` WHERE `password` = MD5('test');
Using MSSQL you can do:
SELECT * FROM [user] WHERE [password] = HASHBYTES('MD5', 'test')
So to extend this to a named query you would create an .hbm.xml file like 'User.hbm.xml' with the following content:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="My.Model" namespace="My.Model">
<sql-query name="GetUserByCredentials">
<return class="My.Model.User, My.Model" />
<![CDATA[
SELECT * FROM User WHERE Username = :Username AND Password = MD5(:Password)
]]>
</sql-query>
</hibernate-mapping>
To configure this I used Fluent NHibernate but something similar would be possible with just plain NHibernate:
Fluently.Configure()
.Database(MySqlConfiguration.Standard
.ConnectionString(x => x.FromConnectionStringWithKey("Test"))
.AdoNetBatchSize(50))
.Cache(c => c
.UseQueryCache()
.ProviderClass<HashtableCacheProvider>())
.Mappings(m =>
{
m.FluentMappings.AddFromAssemblyOf<IHaveFluentNHibernateMappings>().Conventions.Add(ForeignKey.EndsWith("Id"));
m.HbmMappings.AddFromAssemblyOf<IHaveFluentNHibernateMappings>();
})
.BuildConfiguration();
This statement looks for the ".hbm.xml" files in the assembly with the interface named "IHaveFluentNHibernateMappings"
With this in place you can do the following at session level:
public User GetUserByCredentials(string username, string password)
{
IQuery query = Session.GetNamedQuery("GetUserByCredentials");
query.SetParameter("Username", username);
query.SetParameter("Password", password);
return query.UniqueResult<User>();
}
And by calling the the GetUserByCredentials method, the custom query will be executed.
As you can see password is a string, so you need to convert your MD5 byte array to a string first by using:
System.Text.StringBuilder s = new System.Text.StringBuilder();
foreach (byte b in md5ByteArray)
{
s.Append(b.ToString("x2").ToLower());
}
password = s.ToString();
Good luck!