通常,这样做是为了返回与列表匹配的数据集:
string[] ssn = { "123456789", "987654321" };
var result_set = db.employee.Where(w => ssn.Contains(w.SSN)).ToList();
但是,当通过“始终加密”对SSN列进行加密时,会发生此错误:
SqlException:使用加密的数据类型varchar(9) (encryption_type ='DETERMINISTIC',encryption_algorithm_name = 'AEAD_AES_256_CBC_HMAC_SHA_256',column_encryption_key_name = 'CEK_SSN',column_encryption_key_database_name ='MyCompany') collation_name ='Latin1_General_BIN2'和varchar在以下版本中不兼容 等于运算符。
一般情况下,由于单个值有效,因此设置正确:
string ssn = "123456789";
var result_set = db.employee.Where(w => w.SSN == ssn).ToList();
我正在寻找实现此客户端的最佳方法。我知道这种解决方法是可行的,但它需要整个表都可以实现:
var result_set = db.employee.ToList().Where(w => ssn.Contains(w.SSN));
我已经看到一些示例(与.NET的较早版本相关,不一定与“始终加密”有关),其中存在一些花哨的扩展名,它们创建了一堆“或”。我还知道,使用表变量,我可以使用存储过程做一些棘手的事情。但是我确实在寻找一种优雅的方式来实现此目的,最好是通过LINQ,但至少是在客户端代码中。我正在确定“始终加密”是否会给新项目带来任何无法逾越的障碍,因此我愿意接受建议。
答案 0 :(得分:1)
您可能必须生成通过or链模拟ssn.Contains(w.SSN)
调用的谓词。创建起来应该很简单。
var result_set = db.employee.Where(GenerateContainsSsn(ssn)).ToList();
Expression<Func<Employee, bool>> GenerateContainsSsn<T>(IEnumerable<T> collection)
{
var param = Expression.Parameter(typeof(Employee));
var body = collection.Select(v =>
Expression.Equal(Expression.Property(param, "SSN"), Expression.Constant(v))
)
.Aggregate((a, b) => Expression.OrElse(a, b));
return Expression.Lambda<Func<Employee, bool>>(body, param);
}
如果可用,最好寻找一个支持始终加密功能的linq驱动程序,或者至少可以选择生成兼容的查询。