基本上,我有一个具有加密字符串的POCO模型。使用EF core 2.2。
我们使用DECRYPTBYKEY来使用SYMMETRIC KEY解密字符串。
我正在使用DBSet.FromSQL传递SQL查询,该查询调用打开对称密钥,获取包括解密值,关闭对称密钥的数据。
FromSQL仅允许您单独带回实体而不是字符串。
我尝试在模型上添加解密的字符串值,然后尝试在FromSQL查询中进行设置。
[当存储库DBSet中没有任何包含时,实际上填充为OK。
[当DBSet确实具有.include(用于过滤外键表上的DBSet)时,会出现运行时错误,该错误抱怨解密的字符串不是数据库表上的列-当然不是。因此,具有.include会首先在基表上调用SQL。
如果将[NotMapped]属性放在解密的字符串列上,则当FromSQL查询运行时不会填充它。
因此,如何在不使用[NotMapped]的情况下使用此解密的字符串列,而在DBSet上使用.include呢?
我已添加代码,因此您可以查看更多问题。正如一个答案中所建议的那样,无法在模型上添加Decrypt的实现。 Decrypt方法要求DbSet调用FromSQL。 DbSet的来源来自ConcreteRepository。我也无法看到调用临时SQL查询返回1个字符串。
原始SQL片段(SQL Server)
OPEN SYMMETRIC KEY {1} DECRYPTION BY PASSWORD = '{2}';
SELECT * , --other fields
CONVERT(VARCHAR(60), DECRYPTBYKEY(A.Encrypted)) AS Decrypted
FROM dbo.Model A
JOIN table2 t2 ON ...
JOIN table3 t3 ON ...
WHERE A.Id= 123
CLOSE SYMMETRIC KEY {1};",
具体存储库
public async Task<IEnumerable<Model>> GetAllById(int id)
{
var filteredSet = Set.Where(x => x.Id == id)
.Include(x => x.Table2)
.Where(x => x.Table2.IsSomething).ToList();
var models = filteredSet.Select(f =>
GetDecryptValue($"Id = {f.Id}");
return models;
}
基础存储库
protected DbSet<TEntity> Set => _dbContext.Set<TEntity>();
public virtual TEntity GetDecryptValue(string filterCriteria)
{
string buildSelectStmt = $"SELECT TOP 1 Encrypted FROM Model";
string buildSelectStmt2 = $"SELECT *, CONVERT(VARCHAR(MAX), DECRYPTBYKEY(@Value)) AS Decrypted FROM Model";
buildSelectStmt = $"{buildSelectStmt} WHERE {filterCriteria}";
buildSelectStmt2 = $"{buildSelectStmt2} WHERE {filterCriteria}";
string sql = string.Format(@"
DECLARE @Value NVARCHAR(MAX)
SET @Value = ({0});
OPEN SYMMETRIC KEY {1} DECRYPTION BY PASSWORD = '{2}';
{3};
CLOSE SYMMETRIC KEY {1};",
buildSelectStmt, SymmetricKeyName, SymmetricKeyPassword, buildSelectStmt2);
var result = Set.FromSql(sql);
return result.FirstOrDefault();
}
模型
public partial class Model
{
public int Id { get; set; }
public string Encrypted { get; set; }
[NotMapped]
public string Decrypted { get; set; }
}
根据我的收集,您可能仍想使用自定义getter / setter引入[NotMapped]属性:
class Model {
public string Encrypted {get;set}
[NotMapped]
public string Decrypted {
get { return Decrypt(Encrypted);}
set { Encrypted = Encrypt(value);}
}
}
当然,您需要提供加密/解密的实现