如何解决DataGrid告警更新时重复新增及未触发更新的问题
问题描述
我正在开发一款读取邮件、提取数据并将其以告警/通知形式展示在DataGrid中的应用,数据存储于数据库。
场景说明
当新邮件数据到达时,若同一客户在特定时长(如5分钟)内未发送结果相反的告警(如第一个为FAIL,第二个为SUCCESS即互为否定),则更新DataGrid中的对应告警。
当前问题
尝试更新告警时,会新增重复项导致表格混乱,且当相反结果的告警到达时未触发更新。
注意
实际为大型应用,此处以控制台应用示例,仅需少量修改即可适配原应用。
现有代码
读取并提取数据的方法
public void MailKitLib(EmailParser emailParser) { using (var client = new ImapClient()) { using (var cancel = new CancellationTokenSource()) { client.Connect(emailParser.ServerName, emailParser.Port, emailParser.isSSLuse, cancel.Token); client.Authenticate(emailParser.Username, emailParser.Password, cancel.Token); var inbox = client.Inbox; inbox.Open(FolderAccess.ReadOnly, cancel.Token); Console.WriteLine("Total messages: {0}", inbox.Count); Console.WriteLine("Recent messages: {0}", inbox.Unread); for (int i = 0; i < inbox.Count; i++) { var message = inbox.GetMessage(i, cancel.Token); MyAlert alert = new MyAlert(message.MessageId, message.Date.DateTime, message.Subject, message.Subject); if (!MyAlert.alerts.Any(x => x.Id.Equals(alert.Id))) { MyAlert.alerts.Add(alert); // 可视为将对象保存到数据库的方法 } CheckForUpdates(MyAlert.alerts[i]); } } client.Disconnect(true); } }
检查更新的方法
public void CheckForUpdates(MyAlert alert) { double result = 0; foreach (var item in MyAlert.alerts.Select(x => x.NameOfCustomer.Equals(alert.NameOfCustomer))) { if (item) { for (int i = 0; i < MyAlert.alerts.Count(); i++) { result = MyAlert.alerts[i].Date.Minute - alert.Date.Minute; Console.WriteLine("Result of:" + MyAlert.alerts[i].NameOfCustomer + " " + "and" + " " + alert.NameOfCustomer + " " + "is:" + result); if (result > 0 && result <= 5) { Console.WriteLine("You HAVE TO UPDATE this" + " " + MyAlert.alerts[i].NameOfAlert); MyAlert.alerts[i].NameOfAlert = "UPDATED"; break; } else { Console.WriteLine("You DON'T have to UPDATE this:" + " " + MyAlert.alerts[i].NameOfAlert); } } } } Console.WriteLine("Wave:" + MyAlert.alerts.Count); }
解决方案
1. 解决重复项问题
- 仅通过
MessageId判断重复需确保MyAlert.Id正确映射邮件唯一标识,避免漏判。 - 只处理未读邮件,避免重复提取已处理过的数据:
// 修改遍历逻辑,只处理未读邮件 var unreadMessages = inbox.Search(SearchQuery.NotSeen, cancel.Token); foreach (var uid in unreadMessages) { var message = inbox.GetMessage(uid, cancel.Token); MyAlert alert = new MyAlert(message.MessageId, message.Date.DateTime, message.Subject, message.Subject); if (!MyAlert.alerts.Any(x => x.Id == alert.Id)) { MyAlert.alerts.Add(alert); // 同步保存到数据库 } // 标记邮件为已读,防止重复处理 inbox.AddFlags(uid, MessageFlags.Seen, true, cancel.Token); CheckForUpdates(alert); }
2. 修复相反结果告警未触发更新的问题
- 先为
MyAlert添加告警状态属性(如AlertStatus,取值FAIL/SUCCESS),再修改检查逻辑:
public void CheckForUpdates(MyAlert newAlert) { // 筛选同一客户、5分钟内的历史告警(排除自身) var recentAlerts = MyAlert.alerts .Where(a => a.NameOfCustomer == newAlert.NameOfCustomer && (newAlert.Date - a.Date).Duration() <= TimeSpan.FromMinutes(5) && a.Id != newAlert.Id) .ToList(); foreach (var existingAlert in recentAlerts) { // 判断是否为相反结果 bool isOpposite = (existingAlert.AlertStatus == "FAIL" && newAlert.AlertStatus == "SUCCESS") || (existingAlert.AlertStatus == "SUCCESS" && newAlert.AlertStatus == "FAIL"); if (isOpposite) { // 存在相反告警,移除旧告警(或标记为已解决) MyAlert.alerts.Remove(existingAlert); // 同步更新数据库 Console.WriteLine($"处理客户{newAlert.NameOfCustomer}的相反告警,移除旧记录"); return; } else { // 无相反结果,更新现有告警 existingAlert.NameOfAlert = newAlert.NameOfAlert; existingAlert.Date = newAlert.Date; existingAlert.AlertStatus = newAlert.AlertStatus; // 同步更新数据库 Console.WriteLine($"更新客户{newAlert.NameOfCustomer}的告警信息"); } } }
3. 关键优化点
- 避免直接操作静态集合
MyAlert.alerts,实际应用中应从数据库查询最新数据,保证数据一致性。 - 时间差计算改用
TimeSpan,避免跨小时时仅用Minute计算出现的错误。
内容的提问来源于stack exchange,提问作者Petr
相关产品推荐
相关产品推荐

