我如何更改CSVHelper中字段和字段名称的顺序

时间:2017-11-10 16:53:12

标签: c# asp.net asp.net-mvc entity-framework csvhelper

我正在开发一个asp.net mvc 4 web应用程序+实体框架5.0,我有以下方法调用名为AdvanceSearchStoredProcedure的函数,其中此函数将调用存储过程: -

     public IQueryable<AdvanceSearchSP_Result> AdvanceSearch(NetworkAdvanceSearch na)
      {

        var r = entities.AdvanceSearchStoredProcedure("network",na.AssetTypeID,
        na.ip, na.ipselection, na.mac, na.macselection);
        return r.AsQueryable();           

      }

然后我从我的动作方法中调用此方法如下: -

public ActionResult AdvanceSearchIndexExport(AdvanceSearchSP_Result2 ns)

        {
            var result = WriteCsvToMemory(repository.AdvanceSearch(ns.NetwotkAS).ToList());
            var memoryStream = new MemoryStream(result);
            return new FileStreamResult(memoryStream, "text/csv") { FileDownloadName = "export.csv" };
        }
public byte[] WriteCsvToMemory(IEnumerable<AdvanceSearchSP_Result> records)
      {
          using (var memoryStream = new MemoryStream())
          using (var streamWriter = new StreamWriter(memoryStream))
          using (var csvWriter = new CsvWriter(streamWriter))
          {
              csvWriter.WriteRecords(records);
              streamWriter.Flush();
              return memoryStream.ToArray();
          }
      }

这是我的AdvanceSearchSP_Result及其MetadataType类的部分类: -

[MetadataType(typeof(AdvanceSearchSP_Result_Validation))]

    public partial class AdvanceSearchSP_Result
    {


    }
public class AdvanceSearchSP_Result_Validation{
        [Display(Name="Service Tag")]
        public string SERVICETAG { get; set; }
         [Display(Name = "Serial Number")]
        public string SERIALNO { get; set; }
        [Display(Name = "Resource Tag")]
         public string Tag { get; set; }
        [Display(Name = "Resource Name")]
         public string RESOURCENAME { get; set; }
        [Display(Name = "State")]
         public string StateName { get; set; }
        [Display(Name = "Type")]
         public string TypeName { get; set; }
        [Display(Name = "Site Name")]
         public string sitename { get; set; }
        [Display(Name = "Customer Name")]
         public string cusotmername { get; set; }
         public bool ismanaged { get; set; }
}

现在我在生成的.CSV文件中面临这些问题: -

  1. 字段标题将等于数据库内的列名,而不是AdvanceSearchSP_Result_Validation MetadataType类中定义的。

  2. 第二个问题,我不知道如何更改列的顺序?因为目前订单将是在存储过程中定义的顺序...例如,我如何强制ismanaged成为.csv文件中的第一列?

  3. 我正在使用CSVHelper https://www.nuget.org/packages/CsvHelper/库来进行实际的CSV导出。

    修改 现在我添加了这个类: -

    public sealed class SPMap : ClassMap<AdvanceSearchSP_Result>
        {
            public SPMap()
        {
            Map(m => m.Tag).Name("Resource Tag").Index(0);
            Map(m => m.RESOURCENAME).Name("Asset Name").Index(1);
            Map(m => m.cusotmername).Name("Customer Name").Index(2);
            Map(m => m.sitename).Name("Site Name").Index(3);
            Map(m => m.StateName).Name("Asset State").Index(4);
            Map(m => m.ismanaged).Name("ismanaged").Index(5);
            Map(m => m.TypeName).Name("Technology Type ").Index(6);
            Map(m => m.SERVICETAG).Name("Service Tag").Index(7);
            Map(m => m.SERIALNO).Name("Serial Number").Index(8);
    
        }
        }
    

    然后我修改我的方法以包括如下配置: -

     public byte[] WriteCsvToMemory(IEnumerable<AdvanceSearchSP_Result> records)
          {
              using (var memoryStream = new MemoryStream())
              using (var streamWriter = new StreamWriter(memoryStream))
              using (var csvWriter = new CsvWriter(streamWriter))
              {
                  csvWriter.WriteRecords(records);
                  csvWriter.Configuration.RegisterClassMap<SPMap>();
                  streamWriter.Flush();
                  return memoryStream.ToArray();
              }
          }
    

    但我仍然得到了旧的名字和旧订单......所以似乎public sealed class SPMap : ClassMap<AdvanceSearchSP_Result>没有任何影响...

2 个答案:

答案 0 :(得分:1)

我认为您需要一张地图来指定列的名称和索引:

public sealed class SPMap : ClassMap<AdvanceSearchSP_Result>
{
    public SPMap()
    {
        Map(m => m.SERVICETAG).Name("Service Tag").Index(0);
        Map(m => m.sitename).Name("Site Name").Index(1);
        /*repeat for other properties */
        ..
        .. 
    }
}

然后你需要注册:

csvWriter.Configuration.RegisterClassMap<SPMap>();

我相信会工作。

见: http://joshclose.github.io/CsvHelper/mapping

答案 1 :(得分:1)

public byte[] WriteItem<T>(List<T> collection) where T : class
        {


            Type t = typeof(T);
            string newLine = Environment.NewLine;

            object obj = Activator.CreateInstance(t);
            PropertyInfo[] props = obj.GetType().GetProperties();
            byte[] carriageReturnBytes = System.Text.Encoding.UTF8.GetBytes("\r");

            string text;
            using (MemoryStream ms = new MemoryStream())
            using (StreamReader sr = new StreamReader(ms))
            {
                foreach (PropertyInfo pi in props)
                {
                    byte[] data = System.Text.Encoding.UTF8.GetBytes(pi.Name.ToString() + ",");
                    ms.Write(data, 0, data.Length);
                }

                ms.Write(carriageReturnBytes, 0, carriageReturnBytes.Length);

                foreach (T item in collection)
                {
                    foreach (PropertyInfo pi in props)
                    {
                        string write =
                           Convert.ToString(item.GetType().GetProperty(pi.Name).GetValue(item, null)).Replace(",", " ") + ',';

                        byte[] data = System.Text.Encoding.UTF8.GetBytes(write);
                        ms.Write(data, 0, data.Length);
                    }

                    byte[] writeNewLine = System.Text.Encoding.UTF8.GetBytes(Environment.NewLine);
                    ms.Write(writeNewLine, 0, writeNewLine.Length);
                }

                ms.Position = 0;
                text = sr.ReadToEnd();
                return ms.ToArray();
            }
        }