MVC5+EF6.2中Linq查询列表解密性能优化咨询
MVC5 + EF6.2 列表解密性能优化方案
一、把解密逻辑挪到数据库端(最有效)
如果你的数据库支持自定义函数(比如SQL Server),直接在数据库里实现和C#一致的解密逻辑,通过EF查询直接获取解密后的数据,不用把所有加密数据拉到内存再处理。
比如在SQL Server里创建解密函数后,用EF执行原生SQL:
var grid1 = await _db.Database.SqlQuery<dynamic>(@" SELECT dbo.DecryptField(FirstName) AS FirstName, dbo.DecryptField(LastName) AS LastName FROM vw_LearnerCourse ").ToListAsync();
数据库直接返回解密结果,内存占用和处理时间会大幅降低。
二、优化Decrypt5方法本身
原解密方法存在不少低效点,优化后能显著提升速度:
- 替换低效集合与字符串操作
- 把
ArrayList换成List<int>,避免装箱拆箱开销 - 用
StringBuilder代替strOut +=做字符串拼接,减少频繁内存分配
- 把
- 缓存加密密钥与向量
每次解密都生成Key和IV非常耗时,直接缓存这些值,仅初始化一次 - 优化十六进制解析逻辑
直接通过字符计算十六进制值,比Substring加int.Parse效率高很多
优化后的Decrypt5代码:
// 静态缓存Key和IV,仅初始化一次 private static readonly byte[] _encryptionKey = Encoding.UTF8.GetBytes("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); private static readonly byte[] _salt = new byte[] { /* 你的盐值 */ }; private static readonly byte[] _cachedKey; private static readonly byte[] _cachedIV; static Encryption() { var pdb = new Rfc2898DeriveBytes(_encryptionKey, _salt); _cachedKey = pdb.GetBytes(32); _cachedIV = pdb.GetBytes(16); } public static string Decrypt5(string cipherText) { if (string.IsNullOrWhiteSpace(cipherText)) return null; var sb = new StringBuilder(); var offsets = new List<int> {73, 56, 31, 58, 77, 75}; try { for (int i = 0; i <= cipherText.Length - 1; i += 2) { // 直接解析十六进制字符,避免Substring和int.Parse的开销 var c1 = cipherText[i]; var c2 = cipherText[i + 1]; int val1 = char.IsDigit(c1) ? c1 - '0' : char.ToLower(c1) - 'a' + 10; int val2 = char.IsDigit(c2) ? c2 - '0' : char.ToLower(c2) - 'a' + 10; var intVal = val1 * 16 + val2; var mod = (i / 2) % offsets.Count; var newVal = intVal - offsets[mod] + 256; newVal %= 256; sb.Append((char)newVal); } } catch (Exception err) { throw new Exception(err.Message); } var strOut = sb.ToString().Replace(" ", "+"); var cipherBytes = Convert.FromBase64String(strOut); using (var encryptor = Aes.Create()) { encryptor.Key = _cachedKey; encryptor.IV = _cachedIV; using (var ms = new MemoryStream()) { using (var cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write)) { cs.Write(cipherBytes, 0, cipherBytes.Length); } return Encoding.Unicode.GetString(ms.ToArray()); } } }
三、并行处理解密
如果数据量较大,用并行LINQ利用多核CPU同时处理多条数据:
var grid1 = mylist.AsParallel() .Select(c => new { FirstName = Encryption.Decrypt5(c.FirstName), LastName = Encryption.Decrypt5(c.LastName) }) .ToList();
优化后的Decrypt5是线程安全的,可放心使用并行处理。
四、分页加载数据
如果列表数据量很大,不要一次性拉取所有数据,用EF分页仅加载当前页数据:
int pageNum = 1; int pageSize = 20; var mylist = await _db.vw_LearnerCourse.AsNoTracking() .Skip((pageNum - 1) * pageSize) .Take(pageSize) .ToListAsync(); // 再解密当前页的数据
内容的提问来源于stack exchange,提问作者hncl
相关产品推荐
相关产品推荐

