为什么LINQ不能将数据行添加到数据表中

本文关键字:添加 数据表 数据 LINQ 不能 为什么 | 更新日期: 2023-09-27 18:15:06

为了将expandoojects硬塞进如下网格中,我们进行了两次尝试。

这行不通:

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

为什么?

为什么LINQ不能将数据行添加到数据表中

选择方法

此方法表示的查询直到对象通过直接调用其GetEnumerator方法或在Visual c#中使用foreach或在Visual Basic中使用For Each。

所以这个select永远不会被执行:

data.Select(r => dt.Rows.Add((r as IDictionary<string, object>).Values.ToArray()));
参考http://msdn.microsoft.com/ru-ru/library/bb548891.aspx

我还没有测试过这个,但是试试这样的东西:

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

正如sailor已经指出的,LINQ是惰性求值的。在查询的末尾放置一个.LastOrDefault()将导致执行(因为通过尝试获取最后一个元素,它将执行您的Select()),但是将使您的代码看起来更糟糕!

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

总之,坚持选择2。当性能相同时(就像这种情况),试着让你的代码尽可能"容易"阅读。一个随机的人不需要通读整篇文章就能得到大概的意思。