为什么LINQ无法将数据行添加到DataTable?

时间:2011-11-16 16:32:26

标签: c# linq datatable expandoobject

将ExpandoObjects鞋拔成某种网格,就像下面两次尝试一样。

这不起作用:

var data = _d.Query<dynamic>(_script);         // returns IEnumerable<ExpandoObject>

IDictionary<string, object> c = (IDictionary<string, object>)data.FirstOrDefault();
DataTable dt = new DataTable();

dt.BeginLoadData();
dt.Columns.AddRange(c.Keys.Select(k => new DataColumn(k)).ToArray());
data.Select(r => dt.Rows.Add((r as IDictionary<string, object>).Values.ToArray()));
dt.EndLoadData();

但这样做:

dt.Columns.AddRange(c.Keys.Select(k => new DataColumn(k)).ToArray());
foreach (IDictionary<string, object> r in data)
  dt.Rows.Add(r.Values.ToArray());

为什么?

3 个答案:

答案 0 :(得分:1)

选择方法

  

此方法表示的查询直到该对象才会执行   通过直接调用其GetEnumerator方法或枚举来枚举   通过在Visual C#中使用foreach或在Visual Basic中使用For Each。

所以这个选择永远不会执行:

data.Select(r => dt.Rows.Add((r as IDictionary<string, object>).Values.ToArray()));

参考http://msdn.microsoft.com/ru-ru/library/bb548891.aspx

答案 1 :(得分:0)

我没有测试过这个,但尝试这样的事情:

data.Cast<Dictionary<string, object>>().ToList().ForEach(x => dt.Rows.Add(x.Values.ToArray()));

答案 2 :(得分:0)

正如水手已经指出的那样,LINQ被懒惰地评估了。在查询末尾放置.LastOrDefault()将导致执行(因为通过尝试获取最后一个元素它将执行您的Select()),然而它将使您的代码看起来更糟糕的是!

根据定义,LINQ Select不应用于副作用行为。我相信你应该能够在你的问题中看到选项2看起来比选项1更清晰。通过阅读选项2,我可以很容易地理解,你正在将data的每个元素添加到数据表中。通过阅读选项1,我猜你正在对data变量做一些事情,这是错误的。

总之,只需坚持使用选项2.当性能相同时(就是这种情况),尽量使代码“易于”阅读。一个随机的人应该能够在不阅读整个事情的情况下获得一般性的想法。