Доступ к содержимому IQueryable/System.Collections.Generic.List?

У меня есть приложение MVC5/Code-First, которое я разрабатываю с помощью Entity Framework. В настоящее время я пытаюсь добавить функцию экспорта в Excel для динамического вывода выбранных пользователем свойств моей модели INV_Assets. С помощью библиотеки EPPlus и Linq.Dynamic мне удалось экспортировать свои данные в excel, но не совсем корректно.

Я получил заголовки для экспорта в строку 1, но мне все еще трудно экспортировать данные. В настоящее время все данные для моих выбранных полей встречаются, но каждое значение экспортируется в виде длинной строки в свою собственную строку в столбце A. Например, если я выбираю следующие поля (Status, ip_address, mac_address, примечание, владелец, стоимость, po_number и описание) получаю следующее:

Ряд 1: [Status][ip_address][mac_address][note][owner][cost][po_number][description]

Ряд 2: [{Status=SIGNEDOUT, ip_address=10.10.121.25, mac_address=10.10.134.11, note=, owner=John Smith, cost=35.00, po_number=G348, description=This is a description of the item.}][][][][][][][]

Вот изображение вывода, которое я сейчас получаю в Excel:

ExcelOutput

Когда я устанавливаю свою переменную IQueryable (selectStatement) в качестве переменной Watch в VS2013, я могу углубиться в содержимое, но я не могу понять, как получить доступ к этому содержимому по отдельности в коде:

IQueryable

В настоящее время я использую свой IQueryable и загружаю его в Excel с помощью метода EPPlus LoadFromCollection(), но если я смогу понять, как получить доступ к отдельному содержимому моего IQueryable, я смогу настроить некоторые счетчики и циклы, чтобы правильно установить ячейки, которые я хочу, вместо того, чтобы сбрасывать все. в столбец А.

Кто-нибудь может помочь с этим? Полный код для моего ExportController ниже:

    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);
        }

        IQueryable selectStatement = DynamicSelectionColumns(exportFields);

        // 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();
        }

        // Place contents of IQueryable into Excel -- currently dumps selected value for each record into rows with all values for the row as a long string in ColumnA
        if (selectStatement.Count() > 0)
        {
            ws.Cells["A2"].LoadFromCollection(selectStatement.Cast<object>(), true);
        }

        int cnt = 20;
        foreach (var item in selectStatement)
        {
            ws.Cells["A" + cnt].LoadFromCollection(selectStatement.Cast<object>(), false);
            cnt++;

        }


        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);
    }

    public IQueryable DynamicSelectionColumns(List<string> fieldsForExport)
    {
        using (var db = new InventoryTrackerContext())
        {
            string fieldIds = "," + "4,5,3,2,6,17,11,12" + ",";

            var taskColum = Enum.GetValues(typeof(EnumTasks)).Cast<EnumTasks>().Where(e => fieldIds.Contains("," + ((int)e).ToString() + ",")).Select(e => e.ToString().Replace("_", ""));

            //string select = "new (  TaskId, " + (taskColum.Count() > 0 ? string.Join(", ", taskColum) + ", " : "") + "Id )";
            string select = "new (  " + string.Join(", ", fieldsForExport) + ")";

            //return db.INV_Assets.ToList().Select(t => new DynamicColumns() { Id = t.Id, TaskId = Project != null ? Project.Alias + "-" + t.Id : t.Id.ToString(), 
            return db.INV_Assets.ToList().Select(t => new DynamicColumns()
            {
                Id = t.Id,
                Manufacturer = Convert.ToString(t.Manufacturer.manufacturer_description),
                Type = t.Type.type_description,
                Location = t.Location.location_room,
                Vendor = t.Vendor.vendor_name,
                Status = t.Status.status_description,
                ip_address = t.ip_address,
                mac_address = t.mac_address,
                note = t.note,
                owner = t.owner,
                //Module = t.Module != null ? t.Module.Name : "", 
                cost = t.cost,
                po_number = t.po_number,
                description = t.description,
                invoice_number = t.invoice_number,
                serial_number = t.serial_number,
                asset_tag_number = t.asset_tag_number,
                acquired_date = t.acquired_date,
                disposed_date = t.disposed_date,
                verified_date = t.verified_date,
                created_date = t.created_date,
                created_by = t.created_by,
                modified_date = t.modified_date,
                modified_by = t.modified_by
            }).ToList().AsQueryable().Select(select);
        }
    }
}

public class DynamicColumns : INV_Assets
{
    public string Model { get; set; }
    public string Manufacturer { get; set; }
    public string Type { get; set; }
    public string Location { get; set; }
    public string Vendor { get; set; }
    public string Status { get; set; }
    public string ip_address { get; set; }
    public string mac_address { get; set; }
    public string note { get; set; }
    public string owner { get; set; }
    public decimal cost { get; set; }
    public string po_number { get; set; }
    public string description { get; set; }
    public int invoice_number { get; set; }
    public string serial_number { get; set; }
    public string asset_tag_number { get; set; }
    public DateTime? acquired_date { get; set; }
    public DateTime? disposed_date { get; set; }
    public DateTime? verified_date { get; set; }
    public DateTime created_date { get; set; }
    public string created_by { get; set; }
    public DateTime? modified_date { get; set; }
    public string modified_by { get; set; }
}

public enum EnumTasks
{
    Model = 1,
    Manufacturer = 2,
    Type = 3,
    Location = 4,
    Vendor = 5,
    Status = 6,
    ip_address = 7,
    mac_address = 8,
    note = 9,
    owner = 10,
    cost = 11,
    po_number = 12,
    description = 13,
    invoice_number = 14,
    serial_number = 15,
    asset_tag_number = 16,
    acquired_date = 17,
    disposed_date = 18,
    verified_date = 19,
    created_date = 20,
    created_by = 21,
    modified_date = 22,
    modified_by = 23
}

person Analytic Lunatic    schedule 10.03.2015    source источник
comment
@ Эрик Дж., хорошо? Как только я передаю эту строку кода и проверю dbg в Immediate Window, я получаю Count 14 с каждым перечисленным свойством 0-13.   -  person Analytic Lunatic    schedule 11.03.2015
comment
Добавил правильный ответ.   -  person Eric J.    schedule 11.03.2015


Ответы (1)


Вывод, который вы получаете в своих ячейках без заголовка:

Status=SIGNEDOUT, ip_address=10.10.121.25, mac_address=10.10.134.11, note=, owner=John Smith, cost=35.00, po_number=G348, description=Это описание предмета.

выглядит как объект, представленный как property=value, разделенный запятыми. Я предполагаю, что метод ToString() объекта переопределен и создает этот вывод.

Поскольку вы передаете свои строго типизированные объекты в System.Object

selectStatement.Cast<object>()

это, вероятно, лучшее, что может сделать EPPlus.

Попробуйте не приводить его к System.Object, например.

ws.Cells["A2"].LoadFromCollection(selectStatement, true);

Вот статья, которая показывает правильное использование LoadFromCollection

http://www.sitecorecleveland.com/resources/blogs-posts/easy_excel_interaction_pt5

ОБНОВЛЕНИЕ

Ошибка

Аргументы типа для метода «OfficeOpenXml.ExcelRangeBase.LoadFromCollection(System.Collection.Generic.IE‌​numerable, bool)» нельзя вывести из использования. Попробуйте явно указать аргументы типа.

говорит вам, что вам нужно указать фактический тип, возвращаемый запросом (вместо указания object).

ws.Cells["A2"].LoadFromCollection(selectStatement.Cast<DynamicColumns>(), true);
person Eric J.    schedule 10.03.2015
comment
Кажется, я понимаю, о чем вы говорите, но когда я удаляю флаги Cast(), а затем ws.Cells["A2"].LoadFromCollection(selectStatement, true); в VS2013 как "The type arguments for method 'OfficeOpenXml.ExcelRangeBase.LoadFromCollection<T>(System.Collection.Generic.IEnumerable<t>, bool)' cannot be inferred from the usage. Try specifying the type arguments explicitly."...? - person Analytic Lunatic; 11.03.2015
comment
Смотрите мое обновление. Я думаю, что DynamicColumns является правильным типом данных на основе вашего примера кода, но не уверен. - person Eric J.; 11.03.2015
comment
Хм... Я не уверен. Когда я пытаюсь ws.Cells["A2"].LoadFromCollection(selectStatement.Cast<DynamicColumns>(), true);, я получаю во время выполнения: An exception of type 'System.InvalidCastException' occurred in System.Core.dll but was not handled in user code. Additional information: Unable to cast object of type 'DynamicClass1' to type 'InventoryTracker.Controllers.DynamicColumns'. A Cast() as DynamicClass однако выполняет код так же, как и приведение к object, со всеми проходящими значениями; но как длинная строка в столбце A. - person Analytic Lunatic; 11.03.2015
comment
Я добился некоторого прогресса и задался вопросом, не могли бы вы взглянуть на другой вопрос? stackoverflow .com/questions/28988951/ - person Analytic Lunatic; 11.03.2015
comment
Я предложил ответ на другой вопрос. - person Eric J.; 11.03.2015