如果当前行有数据问题,如何在构建 IEnumerable 时移动到下一条记录

How to Move to next record while building an IEnumerable if the current row has data problems

我有一个方法可以输出 class 的 RSVP 列表。 RSVP 基于来自 SQL table 的拉取,保存 RSVP 记录,基于 class id 的输入参数。然后制作所有学生(回复class 的人)的字典。最后我根据每个学生的数据输出了 RSVP 的 IEnumerable。

我 运行 遇到的问题是我在数据中有几个学生 "bad users":他们不在系统中。可能是因为错误的记录删除或错误的创建。无论哪种方式,我都需要在构建 IEnumerable 时为 "bad student records" 设置错误处理。

我的想法是在评估这一行的学生 ID 时发现潜在的错误:

var data = x.ToRsvpData(students[x.RawAgentId]);

然后跳过该记录并转到下一个记录。但是,我不确定该怎么做。

完整方法如下:

public IEnumerable<RsvpData> GetAllRsvpsFor(Guid scheduledId)
    {
        var rsvps = _sors.AnyRsvpsIn(new[] { scheduledId })[scheduledId];
        var certificates = _sors.CertificatesIn(rsvps.Select(x => x.RsvpId).ToList());

        var students = _sors.StudentsBy(rsvps);
        return rsvps.Select(x => {
            var data = x.ToRsvpData(students[x.RawAgentId]);
            if (x.Completed) 
            {
                data.SignatureUrl = StaticContent.S3WebPrefixFor(string.Format("/schools/signatures/{0}.jpg", x.RsvpId.ToString()));
                var cert = certificates.FirstOrDefault(c => c.Rsvp.RsvpId == x.RsvpId);
                data.CertificateId = cert != null ? cert.CertId.ToString() : "";
            }
            return data;
        }).OrderBy(x => x.LastName).ToList();
    }

更新: 这是完整的工作代码:

public IEnumerable<RsvpData> GetAllRsvpsFor(Guid scheduledId)
{
    var rsvps = _sors.AnyRsvpsIn(new[] { scheduledId })[scheduledId];
    var certificates = _sors.CertificatesIn(rsvps.Select(x => x.RsvpId).ToList());

    var students = _sors.StudentsBy(rsvps);

    var cleanRsvpData = new List<RsvpData>();
    foreach (var rsvp in rsvps)
    {
        try
        {
            var data = rsvp.ToRsvpData(students[rsvp.RawAgentId]);
            if (rsvp.Completed)
            {
                data.SignatureUrl = StaticContent.S3WebPrefixFor(string.Format("/schools/signatures/{0}.jpg", rsvp.RsvpId.ToString()));
                var cert = certificates.FirstOrDefault(c => c.Rsvp.RsvpId == rsvp.RsvpId);
                data.CertificateId = cert != null ? cert.CertId.ToString() : "";
            }
            cleanRsvpData.Add(data);
        }
        catch (Exception ex)
        { //Bad Student record
            Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
        }
    }

根据是什么让它们的记录特别不正常,只需将您的 Enumerable 包装在另一个 Enumerable 中就可以解决问题。像这样:

IEnumerable<Record> GetCorrectRecords(IEnumerable<Record> records)
{
   foreach(var record in records)
     if(record.Valid)               // up to you how you define this
       yield return record;
}

您可以使用著名的 try...catch 块来做到这一点,如下所示:

public IEnumerable<int> GetAllRsvpsFor(Guid scheduledId)
    {
        //all the code that precedes the loop
        //for or foreach loop
        {
            //any code that you have to perform after this block
            try
            {
                var data = x.ToRsvpData(students[x.RawAgentId]);
            }
            catch
            {
                continue; //continues to the next for iteration in case of any error
            }
            //any code that you have to perform after this block
        }
    }

最好不要使用 lambda 表达式,而是使用临时列表变量并使用 try catch 块 - 因此只有 "clean" 条记录会进入您的列表:

List<RsvpData> cleanRsvpData = new List<RsvpData>();
        foreach (RsvpData rsvp in rsvps)
        {
            try
            {
                RsvpData data = rsvp.ToRsvpData(students[x.RawAgentId]);
                if (rsvp.Completed)
                {
                    data.SignatureUrl = "test";
                    var cert = certificates.FirstOrDefault(c => c.Rsvp.RsvpId == x.RsvpId);
                    data.CertificateId = cert != null ? cert.CertId.ToString() : "";
                }
                cleanRsvpData.Add(data);
            }
            catch (Exception ex)
            { // handle error here
            }
        }

由于 try catch 位于循环内部,因此如果列表中的某个项目抛出错误,它不会中断整个循环。