导出到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); }
输出 :
我仍然唯一的问题是我的模型中的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 Type
的ForeignKey
值导入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_Assets
与INV_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文件:
当然执行当前导出时,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 }