无法使用 Linq 插入 SQL 服务器始终加密 Table

Cannot Insert into SQL Server AlwaysEncrypted Table with Linq

我完全不在乎这个,所以欢迎提出任何建议。

我是 运行 SQL Server 2016 有两个加密的 tables:

hr_client

[id] [int] IDENTITY(1,1) NOT NULL,
[employee_id] [nvarchar](20) NULL,
[honorific] [nvarchar](20) COLLATE Latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Randomized, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[first_name] [nvarchar](60) COLLATE Latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Randomized, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[last_name] [nvarchar](60) COLLATE Latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Randomized, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[gender] [char](1) COLLATE Latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Deterministic, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[date_of_birth] [date] ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Deterministic, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[national_insurance] [nvarchar](9) COLLATE Latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Randomized, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[start_date] [date] ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Deterministic, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[end_date] [date] ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Deterministic, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[position] [int] ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Deterministic, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[department] [int] ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Deterministic, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[manager] [nvarchar](20) COLLATE Latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Deterministic, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[grade] [nvarchar](20) COLLATE Latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Deterministic, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[salary] [decimal](10, 2) ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Deterministic, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[status] [int] NULL,
[modify_date] [datetime] NULL,
[user_modify] [nvarchar](20) NULL,
[active] [bit] NULL,
[type] [nvarchar](20) NULL

hr_grade

[id] [int] IDENTITY(1,1) NOT NULL,
[grade_id] [nvarchar](20) NULL,
[description] [nvarchar](30) NULL,
[min_rate] [decimal](10, 2) ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Randomized, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[max_rate] [decimal](10, 2) ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Randomized, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[overtime_1] [decimal](5, 2) ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Randomized, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[overtime_2] [decimal](5, 2) ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Randomized, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[modify_date] [datetime] NULL,
[user_modify] [varchar](20) NULL,
[comments] [varchar](max) NULL,
[status] [int] NULL,
[active] [bit] NULL,
[type] [nvarchar](20) NULL,
[position] [int] NULL,

我已经设置了列主密钥和列加密密钥(当前存储在 SQL 服务器上)。我还设置了存储过程以从这两个 table 插入和 Select 数据。数据按预期加密,可以使用存储过程插入和返回数据(直接在 SSMS 中一切正常)。

为了访问数据,我在我们的内部 IIS Web 服务器上创建了一个 ASP MVC 应用程序 运行。该应用程序的目标是 4.6.1,我将 LinqToSql dbml 用于我的 SQL 连接和命令。连接字符串如下:

Data Source=EXAMPLE_IP;Column Encryption Setting=enabled;Initial Catalog=hr;Persist Security Info=True;User ID=EXAMPLE_USER;

数据可以毫无问题地插入 hr_grade table 和从中选择。

但是我只能从 hr_client table SELECT,并且 INSERT(直接或通过存储过程)因以下错误而失败:

Operand type clash: 
nvarchar(4000) encrypted with (
    encryption_type = 'RANDOMIZED', 
    encryption_algorithm_name = 'AEAD_AES_256_CBC_HMAC_SHA_256', 
    column_encryption_key_name = 'EXAMPLE_KEY_NAME', 
    column_encryption_key_database_name = 'hr'
) is incompatible with nvarchar(20) encrypted with (
    encryption_type = 'RANDOMIZED', 
    encryption_algorithm_name = 'AEAD_AES_256_CBC_HMAC_SHA_256', 
    column_encryption_key_name = 'EXAMPLE_KEY_NAME', 
    column_encryption_key_database_name = 'hr')

现在我能看到的唯一明显区别是 hr_client table 有 NVARCHAR 列,我的应用程序似乎不喜欢它。

有什么想法/建议吗?

你应该使用探查器来验证,但我怀疑 Linq2SQL 正在声明一个 nvarchar(4000) 类型的参数以插入到 nvarchar(20) 列中。使用客户端加密,SqlParameter 类型和长度必须与目标列相匹配,因为 SQL 服务器无法对该值执行任何服务器端转换。

您可能需要直接使用 EF 或 ADO.NET。