使用泛型时CsvHelper写入CSV失败的问题排查
问题:CsvHelper写入泛型类型CSV时提示"No properties are mapped"
环境
C# 10 | .NET 6 | CsvHelper 29.0.0
代码实现
尝试用CsvHelper写入泛型类型的CSV,代码如下:
public async Task RunAsync<T>() { List<T> dataList = default!; dataList = await ApiService.GetDataAsync<T>(Job.Read); try { string path = $"./inbox/read.{typeof(T).Name}.csv"; CsvConfiguration config = new(System.Globalization.CultureInfo.InvariantCulture); using StreamWriter sw = new(path, append: false); using CsvWriter csvWriter = new(sw, config); _ = csvWriter.Context.AutoMap<T>(); await csvWriter.WriteRecordsAsync(dataList); } catch { ... } }
错误信息
所有类型都触发如下错误:
No properties are mapped for type 'Ecms.Common.Models.HRTEMP'.
IWriter state:
Row: 2
Index: 0
HeaderRecord: 2
测试类型示例
其中一个测试类型HRTEMP的定义:
public class HRTEMP { public string? ABBRV; // Abbrv public DateTime? ADDDATE; // Added Date public string? ADDR1; // Addr 1 public string? ADDR2; // Addr 2 public string? ADDR3; // Addr 3 public DateTime? ADJHIREDATE; // Adj Hire Date public int? AREACODE; // A/C public string? BUSUFFIX; // Bus Suffix public int? CELLPHAC; // Cell A/C public int? CELLPHNO; // Cell No public string? CITY; // City public string? CNTRYCODE; // Country Code public string? COBRASNTFLG; // COBRA Ltr Sent public int? COMPANYNO; // Src Com public int? CONTACTAC; // Contact A/C public string? CONTACTNAME; // Contact Name public int? CONTACTPHONE; // Contact Phone public int? COUNTYCODE; // County Code public int? DEPTNO; // Dept No public DateTime? DISABILITYDT; // Disability Date public int? DIVISIONNO; // Src Div public string? ELGBRHIRE; // Elig To Rehire public DateTime? ELIGSCKACCRL; // Sick Elig Date public int? EMPCNCID; // Emp SYTCNC Id public int? EMPCOMPANY; // Emp Com No public int? EMPDIVISION; // Emp Div No public int? EMPLCLASS; // Empl Cls public string? EMPLNAME; // Empl Name public int? EMPLOYEENO; // Empl No public string? EMPLTYPE; // Empl Type public DateTime? ESTAVAILDATE; // Est Avail Date [JsonPropertyName("EXPIREDATE")] public DateTime? EXPRIEDATE; // Expiration Date public string? FIRSTNAME25; // First Name public DateTime? HOLELIGDATE; // Hol Elig Date public int? HRTEMPID; // HRTEMP Rec Id public int? HRTOCCID; // public DateTime? LASTDAYWK; // Last Date Wkd public string? LASTNAME25; // Last Name public DateTime? LASTYEDATE; // Last Y/E Date public int? LVLCODE; // LBCC Level Security public string? MIDDLENAME1; // Middle Name 1 public string? MIDDLENAME2; // Middle Name 2 public string? OCCUPDESC1; // Occupation Desc 1 public string? OCCUPDESC2; // Occupation Desc 2 public string? OFFICERSCODE; // Com Officer public DateTime? ORIGHIREDATE; // Orig Hire Date public int? PHONENO; // Phone No public int? PRTECLID; // PRTECL Rec ID public int? PRTLBRID; // PRTLBR Rec ID public int? PRTMSTID; // PRTMST Rec Id public int? PRTTRMID; // PRTTRM Rec ID public DateTime? REHIREDATE; // Re-Hire Date public DateTime? RETIREDDATE; // Retired Date public DateTime? REVIEWDATE; // Review Date public DateTime? SICKACRLDATE; // Sick Accrl Date public int? SRCCNCID; // Src SYTCNC Id public string? STATECODE; // St/Prov public string? STATUSCODE; // Record Code public int? SUPERVISOR1; // Supv 1 Empl public int? SUPERVISOR1CO; // Supv 1 Com public int? SUPERVISOR1DV; // Supv 1 Div public int? SUPERVISOR2; // Supv 2 Empl public int? SUPERVISOR2CO; // Supv 2 Com public int? SUPERVISOR2DV; // Supv 2 Div public int? SUP1MSTID; // Supv 1 PRTMSTID public int? SUP2MSTID; // Supv 2 PRTMSTID public int? SYTTXTID; // SYTTXT Rec Id public int? TERMCODE; // Term Code public DateTime? TERMDATE; // Term Date public int? TERMRSN; // Term Reason Code public string? UPDATEDBY; // UpDated By User public DateTime? UPDDATE; // Last UpDated public string? UPDPGM; // UpDated By Pgm public DateTime? VACELIGDATE; // Vac Elig Date public string? ZIPCODE; // Zip/Postal Code public HRTEMP() {} }
即使将csvWriter.Context.AutoMap<T>()改为csvWriter.Context.AutoMap<HRTEMP>(),仍出现相同错误。
解决方法
问题核心是CsvHelper默认只映射类的属性(Property),而你的HRTEMP类中定义的全是字段(Field),不是属性格式。
提供两个修复方案:
方案1:将字段改为属性
把类中的字段定义修改为属性格式,例如:
// 原字段定义 public string? ABBRV; // 修改为属性定义 public string? ABBRV { get; set; }
方案2:配置CsvHelper支持字段映射
如果不想修改类结构,可以在CsvConfiguration中开启字段映射功能:
CsvConfiguration config = new(System.Globalization.CultureInfo.InvariantCulture) { // 允许映射所有字段 ShouldMapField = field => true };
另外,AutoMap的调用可以简化,无需接收返回值:
csvWriter.Context.AutoMap<T>();
修改后的完整代码示例(方案2):
public async Task RunAsync<T>() { List<T> dataList = default!; dataList = await ApiService.GetDataAsync<T>(Job.Read); try { string path = $"./inbox/read.{typeof(T).Name}.csv"; CsvConfiguration config = new(System.Globalization.CultureInfo.InvariantCulture) { ShouldMapField = field => true }; using StreamWriter sw = new(path, append: false); using CsvWriter csvWriter = new(sw, config); csvWriter.Context.AutoMap<T>(); await csvWriter.WriteRecordsAsync(dataList); } catch { // 异常处理逻辑 } }
内容的提问来源于stack exchange,提问作者chrisxfire
相关产品推荐
相关产品推荐

