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

Asp.net MVC结合EF将List转DataTable填充Excel模板获取关联属性问题

问题解决方案

你遇到的问题由两个原因导致:

  1. EF Core Include 方法的使用错误
  2. 原有的 ToDataTable 方法仅支持读取实体的直接属性,无法读取关联导航属性的嵌套字段

方案1:使用匿名类投影(最适合新手,无需修改现有转换方法)

这是成本最低的方案,你原来的ToDataTable方法不需要做任何改动,只需要调整查询逻辑,将需要的字段都投影到平级的匿名类中即可:

第一步:修正查询写法

你原来的.Include(x => x.Component.Select(c=>c.ReferenceNo))写法是错误的,Include加载单实体导航属性直接指定属性名即可,不需要嵌套Select:

public IActionResult Ex2(int id, int idc)
{
    try
    {
        var data = DB.Activitydetails
            .Where(x => x.Activity.Moid == id && x.Activity.Mo.ClientId == idc)
            .Include(x => x.Component) // 正确加载关联的Component实体
            .Select(a => new 
            {
                // 保留原来需要的Activitydetail字段
                a.ActivityDetailId,
                a.ActivityId,
                a.TimeType,
                a.Hours,
                a.ComponentId,
                a.OkQty,
                a.Comments,
                // 新增Component的字段,属性名和Excel占位符保持一致即可
                ComponentName = a.Component.Name,
                ComponentReferenceNo = a.Component.ReferenceNo
            })
            .ToList();
        
        // 直接用投影后的匿名类List转DataTable
        var table11 = ToDataTable(data);
        table11.TableName = "table11";

        // 后面的DataSet填充、导出逻辑完全不变
        var ds = new DataSet();
        ds.Tables.Add(table11);
        ds.Tables.Add("table2");
        ds.Tables["table2"].Columns.Add("col1");
        ds.Tables["table2"].Columns.Add("col2");
        
        FillReport("new2.xlsx", "template_mo1.xlsx", ds);
        string Files = "new2.xlsx";
        byte[] fileBytes = System.IO.File.ReadAllBytes(Files);
        return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, "new2.xlsx");
    }
    catch (Exception ex)
    {
        // 建议此处添加错误日志,方便后续排查问题
        throw;
    }
}

第二步:调整Excel模板占位符

对应你投影的属性名,把Excel里的占位符改成%ComponentName%、%ComponentReferenceNo%即可正常匹配填充。


方案2:改造ToDataTable方法支持嵌套属性读取

如果你不想每次导出都手动写投影,可以改造转换方法,自动识别嵌套属性:

public DataTable ToDataTable<T>(List<T> items, List<string> nestedProps = null)
{
    DataTable dataTable = new DataTable(typeof(T).Name);
    // 先添加实体的直接属性
    PropertyInfo[] directProps = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
    foreach (PropertyInfo prop in directProps)
    {
        // 如果是类类型导航属性(排除字符串),不直接生成列
        if(prop.PropertyType.IsClass && prop.PropertyType != typeof(string))
            continue;
        dataTable.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
    }
    // 添加指定的嵌套属性列
    if(nestedProps != null)
    {
        foreach(var propPath in nestedProps)
        {
            dataTable.Columns.Add(propPath.Replace(".", ""));
        }
    }
    // 填充行数据
    foreach (T item in items)
    {
        var rowValues = new List<object>();
        // 填充直接属性值
        foreach (PropertyInfo prop in directProps)
        {
            if(prop.PropertyType.IsClass && prop.PropertyType != typeof(string))
                continue;
            rowValues.Add(prop.GetValue(item) ?? DBNull.Value);
        }
        // 填充嵌套属性值
        if(nestedProps != null)
        {
            foreach(var propPath in nestedProps)
            {
                object value = item;
                foreach(var propName in propPath.Split('.'))
                {
                    if(value == null) break;
                    var prop = value.GetType().GetProperty(propName);
                    value = prop.GetValue(value);
                }
                rowValues.Add(value ?? DBNull.Value);
            }
        }
        dataTable.Rows.Add(rowValues.ToArray());
    }
    return dataTable;
}

调用的时候只需要传入需要读取的嵌套属性路径即可:

var data = DB.Activitydetails
    .Where(x => x.Activity.Moid == id && x.Activity.Mo.ClientId == idc)
    .Include(x => x.Component)
    .ToList();
var table11 = ToDataTable(data, new List<string> { "Component.Name", "Component.ReferenceNo" });

Excel模板对应的占位符用%ComponentName%、%ComponentReferenceNo%即可。


内容的提问来源于stack exchange,提问作者Rodica A

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 04:12:03