SQL Server AlwaysEncrypted nvarchar类型冲突问题求助(EF6+SQL2016SP2)
解决SQL Server AlwaysEncrypted+EF6筛选加密列的类型冲突问题
核心错误翻译
使用等于运算符时的错误原文翻译:
... 与nvarchar在等于运算符中不兼容。
解决方案
升级并配置正确的数据访问驱动
确保项目使用支持AlwaysEncrypted的Microsoft.Data.SqlClient(而非旧版System.Data.SqlClient),并在EF6的配置文件中指定该驱动:<entityFramework> <providers> <provider invariantName="Microsoft.Data.SqlClient" type="Microsoft.Data.SqlClient.SqlProviderServices, Microsoft.EntityFrameworkCore.SqlServer" /> </providers> </entityFramework>连接字符串必须启用列加密
在EF使用的连接字符串中添加Column Encryption Setting=Enabled,确保客户端能处理加密参数:Server=myServerAddress;Database=MyDb;Trusted_Connection=True;Column Encryption Setting=Enabled;存储过程参数必须完全匹配加密列属性
存储过程的筛选参数需与加密列的类型、长度、排序规则完全一致。例如加密列是nvarchar(11) COLLATE Latin1_General_BIN2,则存储过程参数定义为:CREATE PROCEDURE [dbo].[MyProcedure] @EncryptedParam nvarchar(11) COLLATE Latin1_General_BIN2 AS BEGIN SELECT * FROM MyTable WHERE EncryptedColumn = @EncryptedParam; SELECT COUNT(*) FROM MyTable WHERE EncryptedColumn = @EncryptedParam; ENDEF6中显式指定参数属性
调用存储过程时,手动创建参数并明确指定类型、长度、排序规则,避免EF自动推断导致的不匹配:using (var context = new MyDbContext()) { var param = new SqlParameter("@EncryptedParam", SqlDbType.NVarChar, 11) { Value = "111 222 333 444", Collation = "Latin1_General_BIN2" }; // 执行存储过程获取结果集 var results = context.Database.SqlQuery<MyEntity>("EXEC MyProcedure @EncryptedParam", param).ToList(); // 获取总数的逻辑需单独调用或调整存储过程返回结构 }确认加密列的加密类型与配置一致性
确保加密列使用的是确定性加密(DETERMINISTIC)(随机加密不支持筛选操作),且列的排序规则确实是Latin1_General_BIN2。若修改过排序规则,需重新加密列以确保配置生效:ALTER TABLE MyTable ALTER COLUMN EncryptedColumn nvarchar(11) COLLATE Latin1_General_BIN2 WITH (ENCRYPTED WITH ( ENCRYPTION_TYPE = DETERMINISTIC, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256', COLUMN_ENCRYPTION_KEY = CEK_Auto1 ));避免数据库端隐式类型转换
存储过程的WHERE子句中,禁止对加密列或参数进行类型转换操作,确保客户端加密后的参数直接与加密列匹配,让数据库执行密文比对。
内容的提问来源于stack exchange,提问作者sada
相关产品推荐
相关产品推荐

