You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;
    END
    
  • EF6中显式指定参数属性
    调用存储过程时,手动创建参数并明确指定类型、长度、排序规则,避免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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 08:43:22