2014-11-14 52 views
3

我有以下查询需要DataTable并计算值出现在countField列中的次数。LINQ查询在计算int时失败

var countField = "class" 
var query = from row in myDataTable.AsEnumerable() 
      group row by row.Field<string>(countField) 
      into sumry 
      orderby sumry.Count() descending 
      select new 
      { 
       Text = sumry.Key, 
       CountofRows = sumry.Count() 
      }; 

按预期工作,除非该列包含十进制值。我并不熟悉linq知道要更改什么以允许它计算十进制值的实例。

我该如何使这个语句更健壮,因此它可以用于指定列中包含的任何数据类型?

回答

3

你可以只取出使用DataRow's索引值,并将其转换为string

var query = from row in myDataTable.AsEnumerable() 
     group row by row[countField].ToString() 
     into sumry 
     orderby sumry.Count() descending 
     select new 
     { 
      Text = sumry.Key, 
      CountofRows = sumry.Count() 
     }; 

这应该按预期工作所有类型。

+0

我觉得这很容易。我试图将它转换为一个字符串,但不是与索引器。这工作完美。谢谢! – davids 2014-11-14 18:35:31

1

您可以获取该列的类型并使用反射来调用Field<T>()。 (请参阅调用一般方法的答案:https://stackoverflow.com/a/232621/409259

var columnType = myDataTable.Columns[countField].DataType; 
var method = typeof(DataRowExtensions).GetMethod("Field", new Type[] { typeof(DataRow), typeof(string) }); 
var generic = method.MakeGenericMethod(columnType); 

var query = from row in myDataTable.AsEnumerable() 
      group row by generic.Invoke(null, new object[] { row, countField }) 
      into sumry 
      orderby sumry.Count() descending 
      select new 
      { 
       Text = sumry.Key, 
       CountOfRows = sumry.Count() 
      }; 
+0

这是否比Selman22的答案提供了一个优势?这看起来更复杂,并不总是很糟糕,但我看不出额外的代码提供了什么? – davids 2014-11-14 23:11:27

+1

只有当'ToString()'会丢失可区分不同值的信息时才重要。例如,'DateTime.ToString()'将时间格式化为秒。如果你需要在毫秒时间内分组,那么它就不适合你。我认为所有其他原始类型,'DateTime'到第二个,'ToString'都可以。对于复杂类型,您必须牢记这一点,以确保分组按照需要进行。 – 2014-11-15 01:51:46