【问题标题】:Export data from nested c# classes to csv file将数据从嵌套的 c# 类导出到 csv 文件
【发布时间】:2019-01-11 09:43:44
【问题描述】:

我有以下类可以使用,我想将内容导出/展平为 csv 文件。 我尝试使用 SelectMany,但找不到从公司级别 SalesArea、Node 和 EthernetArea 的底层级别为我的 csv 文件选择字段的方法。 有人可以解释我需要做什么来完成这个吗?

public class Rootobject
{
    public Company[] Companies { get; set; }
}
public class Company
{
    public string ORG_NAME { get; set; }
    public SalesArea[] Salesareas { get; set; }
    public Node[] Nodes { get; set; }
    public EthernetArea[] Ethernetareas { get; set; }
}
public class SalesArea
{
    public string OBJ_NAME { get; set; }
    public string AREA_CTYPE { get; set; }
}
public class Node
{
    public string OBJ_NAME { get; set; }
    public object BUILDING { get; set; }
}
public class EthernetArea
{
    public string OBJ_NAME { get; set; }
    public string AREA_CTYPE { get; set; }
    public Product[] Products { get; set; }
}
public class Product
{
    public string BANDWIDTH_A { get; set; }
    public string CONNECTION_TYPE { get; set; }
}

【问题讨论】:

标签: c#


【解决方案1】:

我确定应该有另一种方法来做到这一点,但无论如何我就是这样做的......

如果我理解正确,您想对数据进行“非规范化”并将集合导出为 CSV。

我用过很多SelectSelectManyJoin

var root = new Rootobject
    {
        Companies = new Company[] {
            new Company
        {
            ORG_NAME = "Co",
            Salesareas = new SalesArea[]{
            new SalesArea {
                OBJ_NAME = "Sa",
                AREA_CTYPE = "SaAr",
            }
        },
            Nodes = new Node[] {
            new Node {
                OBJ_NAME = "No",
                BUILDING = "NoBu"
            }
        },
            Ethernetareas = new EthernetArea[] {
            new EthernetArea {
                OBJ_NAME = "Et",
                AREA_CTYPE = "EtAr",
                Products = new Product[] {
                    new Product {
                        BANDWIDTH_A = "ProA",
                        CONNECTION_TYPE = "ProCon"
                    }
                }
            }
        }
        },
        new Company
        {
            ORG_NAME = "Co2",
            Salesareas = new SalesArea[]{
            new SalesArea {
                OBJ_NAME = "Sa2",
                AREA_CTYPE = "SaAr2",
            }
        },
            Nodes = new Node[] {
            new Node {
                OBJ_NAME = "No2",
                BUILDING = "NoBu2"
            }
        },
            Ethernetareas = new EthernetArea[] {
            new EthernetArea {
                OBJ_NAME = "Et2",
                AREA_CTYPE = "EtAr2",
                Products = new Product[] {
                    new Product {
                        BANDWIDTH_A = "ProA2",
                        CONNECTION_TYPE = "ProCon2"
                    },
                    new Product {
                        BANDWIDTH_A = "ProA3",
                        CONNECTION_TYPE = "ProCon3"
                    }
                }
            }
        }
        }
    }
    };

    var sas = root.Companies.SelectMany(x => x.Salesareas.Select(y => new { Company = x.ORG_NAME, SalesName = y.OBJ_NAME, SalesAreaType = y.AREA_CTYPE }));
    var nodes = root.Companies.SelectMany(x => x.Nodes.Select(y => new { Company = x.ORG_NAME, NodesName = y.OBJ_NAME, NodeBuilding = y.BUILDING }));
    var ethes = root.Companies.SelectMany(x => x.Ethernetareas.SelectMany(y => y.Products .Select(z => new { Company = x.ORG_NAME, EthernetName = y.OBJ_NAME, EthernetArea = y.AREA_CTYPE, BandwithA = z.BANDWIDTH_A, ConnnectionType = z.CONNECTION_TYPE })));

    sas.Join(nodes, x => x.Company, y => y.Company, (x, y) => new {x.Company, x.SalesName, x.SalesAreaType, y.NodesName, y.NodeBuilding})
        .Join(ethes, x => x.Company, y => y.Company, (x, y) => new {x.Company, x.SalesName, x.SalesAreaType, x.NodesName, x.NodeBuilding, y.EthernetName, y.EthernetArea, y.BandwithA, y.ConnnectionType})
        .Dump();

这是结果...

使用集合,您可以按照@Drag And Drop 的建议使用CsvHelper 来生成 CSV 文件.... :)

编辑

我刚刚意识到@Drag And Drop 代码更直接、更简洁、更好...... :)

【讨论】:

  • 感谢最后一段,并为这个问题显示 SelectMany 语法。我无法让自己承认我也写过一篇。它的语法非常混乱,无法以可读的方式对其进行格式化。
【解决方案2】:

定义一个类,该类将在 CSV 中表示您想要的内容。由于模型中的多个对象属性具有相同的名称。
在您的评论中,您选择在属性前面加上类名,因此您应该有类似:

public class CompanyCSV
{
    public string Company_ORG_NAME { get; set; }

    public string SalesArea_OBJ_NAME { get; set; }
    public string SalesArea_AREA_CTYPE { get; set; }

    public string Node_OBJ_NAME { get; set; }
    public string Node_BUILDING { get; set; }

    public string EthernetArea_OBJ_NAME { get; set; }
    public string EthernetArea_AREA_CTYPE { get; set; }

    public string Product_BANDWIDTH_A { get; set; }
    public string Product_CONNECTION_TYPE { get; set; }
}

那么简单:

var result = from c in dataInput.Companies
                from s in c.Salesareas
                from n in c.Nodes
                from e in c.Ethernetareas
                from p in e.Products
                select new CompanyCSV
                {
                    Company_ORG_NAME = c.ORG_NAME,

                    SalesArea_OBJ_NAME = s.OBJ_NAME,
                    SalesArea_AREA_CTYPE = s.AREA_CTYPE,

                    Node_OBJ_NAME = n.OBJ_NAME,
                    Node_BUILDING = n.BUILDING.ToString(),

                    EthernetArea_OBJ_NAME = e.OBJ_NAME,
                    EthernetArea_AREA_CTYPE = e.AREA_CTYPE,

                    Product_BANDWIDTH_A = p.BANDWIDTH_A,
                    Product_CONNECTION_TYPE = p.CONNECTION_TYPE
                };


foreach (var line in result)
{ // Don't use this to generate your csv this is simply to show the result
    Console.WriteLine($"{line.c},{line.s},{line.n},{line.e},{line.p}, ..etc ..");
}

要编写 CSV,您可以使用 CsvHelper。 这将帮助您使用逗号或引号处理值。不要手动生成 CSV。

如果您的集合(Node[]、Company[] 等)可以为 null,您应该在 getter 中使用 null-coalescing operator 来保护这种极端情况,例如:

private Node[] nodes;
public Node[] Nodes {
    get { return nodes ?? (nodes = new Node[] { }); }
    set { nodes = value; }
}

【讨论】:

  • 如何定义您建议的课程?我试过了,但没有用: public class dataInput { public string Companies { get;放; } 公共字符串 Salesareas { 获取;放; } 公共字符串节点 { 获取;放; } 公共字符串以太网区域 { 获取;放; } 公共字符串产品 { 获取;放; } }
  • 像任何其他类一样:public class MyCSV{ public type propertyName; ... 具有可理解的名称等。然后将查询的 select 部分修改为 select new MyCSV{ propertyName = value,...
  • 这是一个令人困惑的编辑:public string Companies? Companies 是一组 Company,具有一个字段 ORG_NAME。和 3 个阵列 Salesareas、Nodes、Ethernetareas。这是一个字符串中的大量信息。想象一下,CSV 的每一列都是一个属性。这个属性在复杂对象中的位置没有问题。写下您拥有的每个 csv 列,并在旁边写下它在对象中的位置。列列表的第一部分将是您的输出对象定义
  • 非常感谢您的建议,我现在可以为 Company 和 Salesarea 生成输出。我现在遇到的问题是选择节点。在我的输入数据中,它们可以为 NULL,但它们也可以由多个 Node 对象组成。我当前在 MyCSV 中对字段 OBJ_NAME(来自节点)的声明是: public string Nodes_OBJ_NAME { get;放;我猜这个声明导致了这个问题?我应该如何声明这个字段,使其与类节点中的相应字段相匹配?
  • 例如,Nodes=null。你有一个问题,'NullReferenceException'。为什么节点不是空集合?想象一个可能有孩子也可能没有孩子的人,如果你问他有几个孩子,他是否必须:回答 1/。中风并死去。 2/。数一数,答案为 0。如果简单地唤起孩子这个词必须杀死他,那么 null 就可以了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-05-19
  • 2015-09-01
  • 1970-01-01
  • 2014-01-09
  • 2018-04-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多