song.jun
3 天以前 ed655574fc9dc7c6c67dceddcdebb7a25c16d244
优化 SaveLabList 路径的 DB 查询次数(P2.5)

之前 QCDistributionInfoViewModel.ToEntity 对 LabList 里的每个条目做
3 次独立 DB 查询(ToEntity 内部按 Id 查、查重按 LabId+ProjectId 查、
删除分支按 Id 查),100 行 LabList 就是 ~300 次 round-trip + 每次
Save 自己的 SaveChanges,在线上实际请求耗时几秒到十几秒。

优化:
- QCDistributionRegisterInfoViewModel.ToEntity 加重载 (viewModel,
preloadedExisting),允许调用方传入已查好的 tracked entity 跳过内部
DB 查询;原签名保留(fallback 到 DB 查)不影响其他调用方。
- SaveLabList 循环前一次性 WHERE QCDistributionId=? 拉取当前分发全部
登记到内存,建 byId / byLabProject 两个字典,循环内走字典查找。
- 罕见的跨分发 Id 引用走 DB fallback 保持原有语义。
- 删除分支直接复用已缓存的 cachedExisting,去掉独立查询。

100 行 LabList 的 DB round-trip 从 ~300 次降到 1 次预加载 + 实际
Save/Delete 次数。第一道防线和第二道防线的查重语义不变。

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2个文件已修改
43 ■■■■■ 已修改文件
sbcLabSystem/Models/Backstage/QCDistributionInfoViewModel.cs 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sbcLabSystem/Models/Backstage/QCDistributionRegisterInfoViewModel.cs 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sbcLabSystem/Models/Backstage/QCDistributionInfoViewModel.cs
@@ -136,9 +136,23 @@
            if (viewModel.LabList != null && viewModel.LabList.Count > 0)
            {
                var qcService = PalGainEngine.Instance.Resolve<QCService>();
                var existingRegisters = qcService.GetQcDistributionRegisters()
                    .Where(p => p.QCDistributionId == viewModel.Id)
                    .ToList();
                var byId = existingRegisters.ToDictionary(p => p.Id, p => p);
                var byLabProject = existingRegisters
                    .GroupBy(p => Tuple.Create(p.LabId, p.ProjectId))
                    .ToDictionary(g => g.Key, g => g.First());
                viewModel.LabList.ForEach(x =>
                {
                    QCDistributionRegisterInfo registerInfo = QCDistributionRegisterInfoViewModel.ToEntity(x);
                    QCDistributionRegisterInfo cachedExisting = null;
                    if (x.Id > 0 && !byId.TryGetValue(x.Id, out cachedExisting))
                    {
                        cachedExisting = qcService.GetQcDistributionRegisters()
                            .FirstOrDefault(p => p.Id == x.Id);
                    }
                    QCDistributionRegisterInfo registerInfo = QCDistributionRegisterInfoViewModel.ToEntity(x, cachedExisting);
                    registerInfo.QCDistributionId = viewModel.Id;
                    registerInfo.LabId = x.LabId;
                    registerInfo.ProjectId = x.ProjectId;
@@ -146,15 +160,12 @@
                    {
                        if (registerInfo.Id == 0)
                        {
                            var existing = qcService.GetQcDistributionRegisters()
                                .FirstOrDefault(p => p.QCDistributionId == viewModel.Id
                                                  && p.LabId == x.LabId
                                                  && p.ProjectId == x.ProjectId);
                            if (existing != null)
                            QCDistributionRegisterInfo dup;
                            if (byLabProject.TryGetValue(Tuple.Create(x.LabId, x.ProjectId), out dup))
                            {
                                existing.IsCharged = x.IsCharged;
                                existing.ModifyTime = DateTime.Now;
                                qcService.SaveQcDistributionRegister(existing);
                                dup.IsCharged = x.IsCharged;
                                dup.ModifyTime = DateTime.Now;
                                qcService.SaveQcDistributionRegister(dup);
                                return;
                            }
                        }
@@ -163,11 +174,9 @@
                    }
                    else
                    {
                        var entity = qcService.GetQcDistributionRegisters()
                                .FirstOrDefault(p => p.Id == x.Id);
                        if (entity != null)
                        if (cachedExisting != null)
                        {
                            qcService.DeleteQcDistributionRegister(entity);
                            qcService.DeleteQcDistributionRegister(cachedExisting);
                        }
                    }
                });
sbcLabSystem/Models/Backstage/QCDistributionRegisterInfoViewModel.cs
@@ -610,8 +610,14 @@
        }
        public static QCDistributionRegisterInfo ToEntity(QCDistributionRegisterInfoViewModel viewModel)
        {
            QCDistributionRegisterInfo entity = PalGainEngine.Instance.Resolve<QCService>()
            QCDistributionRegisterInfo existing = PalGainEngine.Instance.Resolve<QCService>()
                .GetQcDistributionRegisters().FirstOrDefault(p => p.Id == viewModel.Id);
            return ToEntity(viewModel, existing);
        }
        public static QCDistributionRegisterInfo ToEntity(QCDistributionRegisterInfoViewModel viewModel, QCDistributionRegisterInfo preloadedExisting)
        {
            QCDistributionRegisterInfo entity = preloadedExisting;
            if (entity == null)
            {
                entity = new QCDistributionRegisterInfo();