You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 12:15:40