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

时间:2015-01-30 18:48:30

标签: c# linq

我有一个输出类的RSVP列表的方法。 RSVP基于来自保存RSVP记录的SQL表的拉取,基于类id的输入参数。然后制作一份所有学生的字典(RSVPd到该课程的人)。最后,我根据每个学生的数据输出了RSVP的IEnumerable。

我遇到的问题是我的数据中有几个学生是“坏用户”:他们不在系统中。可能是由于记录删除不良或创建不良。无论哪种方式,我都需要在构建IEnumerable时为“坏学生记录”设置错误处理。

我的想法是在评估此行上的学生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);
        }
    }

3 个答案:

答案 0 :(得分:3)

根据使其成为特别行为不当的记录的原因,只需将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;
}

答案 1 :(得分:1)

你可以使用着名的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
        }
    }

答案 2 :(得分:1)

不是使用lambda表达式,最好的办法是使用临时列表变量并使用try catch块 - 所以只有“干净”的记录才能进入你的列表:

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是INSIDE循环,如果列表中的某个项引发错误,它将不会破坏整个循环。