Currently I'm using SQL Server 2016 to make benefit of Always Encrypted
feature. There are a couple of columns that I should encrypt. I've encrypted those columns with SQL Server. NHibernate
can easily read data from SQL Server
but when it tries to insert data in the DB it will throw an exeption like below:
Operand type clash: nvarchar(4000) encrypted with (encryption_type = 'DETERMINISTIC', encryption_algorithm_name = 'AEAD_AES_256_CBC_HMAC_SHA_256', column_encryption_key_name = 'CEK_Auto1', column_encryption_key_database_name = 'EncTest') is incompatible with nvarchar(250) encrypted with (encryption_type = 'DETERMINISTIC', encryption_algorithm_name = 'AEAD_AES_256_CBC_HMAC_SHA_256', column_encryption_key_name = 'CEK_Auto1', column_encryption_key_database_name = 'EncTest')
This is my column mapping for the specific column in NHibernate
:
<column name="DisableTxt" length="100" sql-type="NVarChar" />
What mapping I should define in my hbm
files?
I found a solution to this problem, first I would like to describe why
NHibernate
can't work withEncrypted Columns
inAlways Encrypted
feature:When we enable
AlwaysEncrypted
in our connection string ,ADO.NET
automatically executes a store proceduresp_describe_parameter_encryption
before any db operations to to determine which parameters correspond to database columns that are protected by using the Always Encrypted feature. This sp is sensitive for the length of the fields and if the specified parameter length isn't equal to the column length, SQL Server will give us error below:This happens because
NHibernate
always define parameter size of4000
forNVarchar
columns (if column length isn'tNVarchar(max)
). So Imagine We've got a column with length of30
butNHibernate
define a parameter with the length of4000
for specified column. WhyNHibernate
does that?if you take a look on
SqlClientDriver.cs
line 146 onNhibernate
source, you will see comment below:So how we can solve this problem? We can create a new
Driver
forNHibernate
which define accurate parameter length. (of course if you don't care about%%
like expressions). (I've used this method onNHiberate 3.x
)