导出到Excel – LINQ – 在.ToList()中包含ForeignKey值?

我试图通过EPPlus库将Excel导出function添加到我的MVC5 / Code-First Entity Framework应用程序。 在我的导出View我已经使用每个INV_Assets模型属性填充了MultiSelectList 。 然后将它们传递到我的ExportController以指定要导出模型的哪些字段。

我已经获得了Headers(通过MultiSelectList )加载到Excel的Row1和来自我的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(); foreach (var selectedField in model.SelectedFields) { // Adds selected fields to [exportFields] List 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); } 

输出

Excel输出

我仍然唯一的问题是我的模型中的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 ,而不是每个单元格中包含"InventoryTracker.Models.INV_Statuses"

任何人都可以深入了解如何不仅导出直接的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()上做错了吗?


编辑2

感谢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; } } 

ExportController

  [HttpPost] public ActionResult ExportUsingEPPlus(ExportAssetsViewModel model) { ExcelPackage package = new ExcelPackage(); var ws = package.Workbook.Worksheets.Add("TestExport"); var exportFields = new List(); foreach (var selectedField in model.SelectedFields) { // Adds selected fields to [exportFields] List 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.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文件:

Excel3

当然执行当前导出时,excel中的[Status]列在每个单元格中包含“InventoryTracker.Models.INV_Statuses”,而不是说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 }