You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用泛型时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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 03:10:28