如果当前行有数据问题,如何在构建 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 位于循环内部,因此如果列表中的某个项目抛出错误,它不会中断整个循环。
我有一个方法可以输出 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 位于循环内部,因此如果列表中的某个项目抛出错误,它不会中断整个循环。