【问题标题】:Converting 1000s ExpandoOject / dynamic to static type takes forever将 1000s ExpandoOject / 动态转换为静态类型需要很长时间
【发布时间】:2018-05-27 00:52:46
【问题描述】:

我正在尝试将 1000 个动态列表(我从 CsvHelper 读取 csv 文件中获得)转换为静态类型,但它需要永远。

代码如下:

动态对象

      MyObj {
               id =1, prop1=1,prop2=2,prop3=3...
            }

结果

           PObj1 { oid = 1 , name = "Property 1", value = "1" }
           PObj2 { oid = 1 , name = "Property 2", value = "2" }
           PObj3 { oid = 1 , name = "Property 3", value = "3" }

要转换的代码

 var imp = rows.SelectMany(x => map.Keys.ToList().Select(k => new PObj
      {
          OID = (((IDictionary<string, object>)x)["oid"] ?? "").ToString(),
          Name = k,
          Value = ToDate((((IDictionary<string, object>)x)[map[k]] ?? "").ToString())
      }).ToList()).ToList();

地图包含大约 40-50 的属性列表

map<string,string>{
                   {"Property 1","prop1"},
                   {"Property 1","prop2"},
                   {"Property 1","prop3"}
                    ...
}

ToDate 函数

private DateTime? ToDate(string strDate)
        {
            strDate = strDate.Split(' ')[0];
            strDate = strDate.Replace('-', '/').Replace('.', '/');
            DateTime? dt = null;
            try
            {
                dt = DateTime.ParseExact(strDate, dateFormats, CultureInfo.InvariantCulture, DateTimeStyles.None);
            } catch { }
            return dt;
        }

map 可以包含任意数量的属性,因此 expandoObject 将具有动态数量的属性。

有什么方法可以提高性能吗?

我需要进行此转换的原因是因为我需要将其作为表发送到存储过程,因此如果对象中的数字属性发生更改,则将 expandoObject 直接转换为表会产生问题,因为此平均列数也会在表中更改.

如果在上述情况下工作,我也愿意接受其他解决方案。

【问题讨论】:

  • 在代码运行时检查任务管理器并查看内存使用情况。 Linq 对象/方法使用大量内存,执行时间缓慢通常是内存问题。
  • 将 ParseExact 更改为 TryParseExact 并查看是否有所作为。假设 ParseExact 有 90% 的时间都失败了,那么这意味着你会产生很多异常,它们是性能杀手
  • @JoostAarts 没有任何区别。顺便说一句,它的逆转,它成功了几乎 95% 的时间
  • 我一定是做错了什么,它只有大约 15k 的动态对象,有 8 个属性,应该创建大约 130k 的对象,这不是很大的数字,但它仍然需要永远
  • 不确定如何,但相同的代码(几乎相同)现在可以正常工作。它在不到一秒的时间内完成了整个列表。 rows.ToList().ForEach(x => imps.AddRange(map.Keys.Select(k => new ImportMilestone { JVSiteID = (((IDictionary)x)[siteid] ?? ""). ToString(), Milestone = k, MilestoneValue = ToDate((((IDictionary)x)[map[k]] ?? "").ToString()) }).ToList()));

标签: c# .net performance dynamic expandoobject


【解决方案1】:

好像是我的电脑(在 Mac 上运行 Windows)。相同的代码现在可以正常工作了

 rows.ToList().ForEach(x => imps.AddRange(map.Keys.Select(k => new ImportMilestone
                    {
                        JVSiteID = (((IDictionary<string, object>)x)[siteid] ?? "").ToString(),
                        Milestone = k,
                        MilestoneValue = ToDate((((IDictionary<string, object>)x)[map[k]] ?? "").ToString())
                    }).ToList()));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多