【问题标题】:Export to Excel - LINQ - Include ForeignKey values in .ToList()?导出到 Excel - LINQ - 在 .ToList() 中包含 ForeignKey 值?
【发布时间】:2015-03-11 14:11:57
【问题描述】:

我正在尝试通过 EPPlus 库将 Excel 导出功能添加到我的 MVC5/Code-First Entity Framework 应用程序。在我的 Export View 上,我用我的每个 INV_Assets 模型属性填充了 MultiSelectList。然后将这些传递到我的ExportController 以指定要导出模型的哪些字段。

我已将标题(通过MultiSelectList)加载到 Excel 的第 1 行,并将我的 INV_Assets 模型中的数据通过 EPPlus LoadFromCollection() 导出到 excel,如下所示(示例):

代码

    [HttpPost]
    public ActionResult ExportUsingEPPlus(ExportAssetsViewModel model)
    {
        ExcelPackage package = new ExcelPackage();
        var ws = package.Workbook.Worksheets.Add("TestExport");

        var exportFields = new List<string>();
        foreach (var selectedField in model.SelectedFields)
        {
            // Adds selected fields to [exportFields] List<string>
            exportFields.Add(model.ListOfExportFields.First(s => s.Key == selectedField).Value);
        }

       {
            ws.Cells[1, i + 1].Value = exportFields[i].ToString();
        }

        var membersToShow = typeof(INV_Assets).GetMembers().Where(p => exportFields.Contains(p.Name)).ToArray();

        ws.Cells["A2"].LoadFromCollection(_db.INV_Assets.ToList(), false, TableStyles.None, BindingFlags.Default, membersToShow);

        var memoryStream = new MemoryStream();
        package.SaveAs(memoryStream);

        string fileName = "Exported-InventoryAssets-" + DateTime.Now + ".xlsx";
        string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";

        memoryStream.Position = 0;
        return File(memoryStream, contentType, fileName);
    }

输出

我仍然存在的唯一问题是我的模型中的 ForeignKey 字段。例如,[Status] 在我的INV_Assets 模型中定义为:

    [Required]
    public int Status_Id { get; set; }
    [ForeignKey("Status_Id")]
    public virtual INV_Statuses Status { get; set; }

当当前导出执行时,Excel 中的[Status] 列在每个单元格中包含"InventoryTracker.Models.INV_Statuses",而不是说AVAILABLE/RECYCLED

谁能提供有关如何不仅将直接的INV_Assets 字段导出,而且将Model, Location, Status, Vendor, Manufacturer, and TypeForeignKey 值也导入Excel 的见解吗?

我做了一些阅读并认为Include() 方法会起作用,但没有运气。 (例如)[Type] 仍然使用以下代码在所有记录单元格中显示 InventoryTracker.Models.INV_Types

ws.Cells["A2"].LoadFromCollection(_db.INV_Assets.Include("Model").Include("Manufacturer").Include("Type").Include("Status").Include("Vendor").ToList(), false, TableStyles.None, BindingFlags.Default, membersToShow);

编辑

我将using System.Data.Entity 添加到我的ExportController 中,这样可以编译以下内容:

ws.Cells["A2"].LoadFromCollection(_db.INV_Assets.Include(m => m.Model.model_description).Include(m => m.Manufacturer.manufacturer_description).Include(m => m.Type.type_description).Include(m => m.Status.status_description).Include(m => m.Vendor.vendor_name).ToList(), false, TableStyles.None, BindingFlags.Default, membersToShow);

我认为这可以解决问题,但在执行过程中我收到:

InvalidOperationException was unhandled by user code.

An exception of type 'System.InvalidOPerationException' occurred in EntityFramework.SqlServer.dll but was not handled in user code.

Additional Information: A specified Include path is not valid. The EntityType 'InventoryTracker.DAL.INV_Models' does not declare a naviation property with the name 'model_description'.

我不明白为什么会以这种方式标记。 INV_AssetsINV_Models 的关系是这样定义的:

    public int Model_Id { get; set; }
    [ForeignKey("Model_Id")]
    public virtual INV_Models Model { get; set; }

而INV_Models定义为:

public class INV_Models
{
    public int Id { get; set; }

    [Required(ErrorMessage = "Please enter a Model Description.")]
    public string model_description { get; set; }

    [Required]
    [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
    public DateTime created_date { get; set; }

    [Required]
    public string created_by { get; set; }

    [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
    public DateTime? modified_date { get; set; }

    public string modified_by { get; set; }
}

谁能发现我在Include() 上做错了什么?


EDIT2

感谢Eric J的建议,问题解决了!在我想要的每个模型上添加了 ToString() 覆盖,以确保通过值而不仅仅是对象类型:

public class INV_Models
{

    public override string ToString()
    {
        return this.model_description;
    }
}

public class INV_Manufacturers
{
    public override string ToString()
    {
        return this.manufacturer_description;
    }
}

public class INV_Locations
{
    public override string ToString()
    {
        return this.location_dept + "|" + this.location_room;
    }
}

public class INV_Vendors
{
    public override string ToString()
    {
        return this.vendor_name;
    }
}

public class INV_Types
{
    public override string ToString()
    {
        return this.type_description;
    }
}

public class INV_Statuses
{
    public override string ToString()
    {
        return this.status_description;
    }
}

导出控制器

    [HttpPost]
    public ActionResult ExportUsingEPPlus(ExportAssetsViewModel model)
    {
        ExcelPackage package = new ExcelPackage();
        var ws = package.Workbook.Worksheets.Add("TestExport");

        var exportFields = new List<string>();
        foreach (var selectedField in model.SelectedFields)
        {
            // Adds selected fields to [exportFields] List<string>
            exportFields.Add(model.ListOfExportFields.First(s => s.Key == selectedField).Value);
        }

        // Loops to insert column headings into Row 1 of Excel
        for (int i = 0; i < exportFields.Count(); i++)
        {
            ws.Cells[1, i + 1].Value = exportFields[i].ToString();
        }

        var membersToShow = typeof(INV_Assets).GetMembers().Where(p => exportFields.Contains(p.Name)).ToArray();

        ws.Cells["A2"].LoadFromCollection(_db.INV_Assets.ToList(), false, TableStyles.None, BindingFlags.Default, membersToShow);



        var membersToShow = typeof(INV_Assets).GetMembers().Where(p => exportFields.Contains(p.Name)).ToArray();

        var memoryStream = new MemoryStream();
        package.SaveAs(memoryStream);

        string fileName = "Exported-InventoryAssets-" + DateTime.Now + ".xlsx";
        string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";

        memoryStream.Position = 0;
        return File(memoryStream, contentType, fileName);
    }

以及输出的 Excel 文件:

【问题讨论】:

    标签: c# asp.net-mvc linq export-to-excel epplus


    【解决方案1】:

    当当前导出执行时,Excel 中的 [Status] 列不会显示 AVAILABLE/RECYCLED,而是在每个导出记录的每个单元格中包含“InventoryTracker.Models.INV_Statuses”。

    这就是在 INV_Statuses 实例上调用 System.Object.ToString() 时得到的结果。

    尝试在该类中覆盖 ToString():

    public class INV_Statuses
    {
        public override string ToString()
        {
            // TODO: Return whatever you would like to have appear in Excel
        }
    
        // Rest of the class here
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-15
      • 1970-01-01
      相关资源
      最近更新 更多