我想在读取文件时应用逻辑,例如清理一串特殊字符,或者如果字段为空,则确定两个日期之间的差异。
我已经在我的地图中尝试了这个:
public InboundPlacementMap()
{
AutoMap();
Map(m => m.HomePhone).ConvertUsing(
rec =>
{
return CleanPhoneNumber(rec.HomePhone);
});
Map(m => m.LengthOfStay).Name("Length of Stay").ConvertUsing(
row =>
{
if (row.LengthOfStay > 0)
return (int)row.LengthOfStay;
return (row.AdmitDate - row.DischargeDate+500).Days;
});
}
private string CleanPhoneNumber(string phone)
{
//Do some logic to remove characters, etc.
return phone;
}
(实际上,CleanPhoneNumber位于一个不同的库中,用于跨项目。)但是调用它有一种我不喜欢的味道,以及它似乎不起作用:
Map(m => m.PatHomePhone).ConvertUsing(rec =>
{ return PamUtility.Utilities.CleanPhoneNumber(rec.PatHomePhone); });
在我阅读的方法中,我使用GetRecords<>()一次阅读所有内容。我最好一个一个地阅读记录,并在阅读每个记录后执行我的逻辑吗? (这对我来说似乎很混乱。)
List<InboundPlacementFileRecord> allRecords = new List<InboundPlacementFileRecord>();
using (TextReader textReader = File.OpenText(fileToRead))
{
var csv = new CsvReader(textReader);
csv.Configuration.Delimiter = "|";
csv.Configuration.IgnoreBlankLines = true;
csv.Configuration.PrepareHeaderForMatch =
header => header.Replace(" ", string.Empty);
csv.Configuration.HeaderValidated= null;
csv.Configuration.MissingFieldFound = null;
csv.Configuration.RegisterClassMap<InboundPlacementMap>();
allRecords = csv.GetRecords<InboundPlacementFileRecord>().ToList();
}
编辑: 作为参考,这里是记录记录的样子,如果有更多的逻辑要执行,会很快变得难看,因此我希望将它放在映射中:
while (csv.Read())
{
var record = csv.GetRecord<InboundPlacementFileRecord>();
record.LengthOfStay=(record.LengthOfStay>0)? record.LengthOfStay :
(int)(record.DischargeDate-record.AdmitDate).TotalDays;
// ... other logic here ...
allRecords.Add(record);
}
(在本期问题时使用最新的CsvHelper,7.1.0。)
答案 0 :(得分:1)
这确实是一个偏好问题。在映射中执行所有操作都很好。内联它也很好。另一个选项而不是ConvertUsing
是创建自定义类型转换器。您可以使用其中一个内置的示例。 https://github.com/JoshClose/CsvHelper/blob/master/src/CsvHelper/TypeConversion/BooleanConverter.cs
GetRecords<T>()
会返回IEnumerable<T>
个yield
个记录。这意味着它只会在每次迭代中拉出一条记录,因此您不必担心内存中的所有数据。如果您执行ToList()
或Count()
之类的操作,它会将所有记录拉入内存,因此请小心。