【问题标题】:Reversing typeof to use Linq Field<T>反转 typeof 以使用 Linq Field<T>
【发布时间】:2012-11-25 23:53:57
【问题描述】:

我想使用 Linq 通过 ColumnName 动态选择 DataTable 列,但要使用 Field 我必须显式地将它们强制转换或将所有内容装箱到一个对象中,这效率不高。

我试过了:

string[] colsNames = new[] { "Colum1", "Colum2" };
DataTable dt = StoredProcedure().Tables[0];

var cols = dt.Columns.Cast<DataColumn>().Where(c => cols.Contains(c.ColumnName));

if (cols.Any())
{
    dt.AsEnumerable().Select(r => string.Join(":", cols.Select(c => r.Field<c.DataType>(c.ColumnName))))
}

但这会给我一个错误The type or namespace name 'c' could not be found

例如,如何将typeof(decimal) 转换为Field&lt;decimal&gt;("Column1")

【问题讨论】:

  • 有什么意义?如果您不知道请求数据的类型,那么您只能处理 object
  • 我知道请求数据的类型
  • 但是你说你是按列名检索数据.. 那么IEnumerable&lt;known_type&gt; requestedData = dt.AsEnumerable().Select(r =&gt; r.Field&lt;known_type&gt;("ColumnName"))有什么问题呢?
  • @lazyberezovsky 因为我正在动态选择列。
  • 那你不知道请求数据的类型

标签: c# linq reflection casting


【解决方案1】:

试试这个:

DataTable dt = new DataTable();
dt.Columns.Add("id", Type.GetType("System.Int32"));
dt.Columns.Add("Colum1", Type.GetType("System.Int32"));
dt.Columns.Add("Colum2", Type.GetType("System.String"));
dt.Columns.Add("Colum3");

string[] colsNames = new[] { "Colum1", "Colum2" };
var colTypes = dt.Columns.Cast<DataColumn>()
                 .Where(c => colsNames.Contains(c.ColumnName))
                 .Select(c => new
                 {
                     c.ColumnName,
                     c.DataType
                 })
                 .ToDictionary(key => key.ColumnName, val => val.DataType);

var query = dt.AsEnumerable()
              .Where(row => (int)row["id"]==5)
              .Select(row => new
              {
                  Colum1 = Convert.ChangeType(row[colsNames[0]], colTypes[colsNames[0]]),
                  Colum2 = Convert.ChangeType(row[colsNames[1]], colTypes[colsNames[1]])
              });

这里还有一个变种,但不是很有趣:

//define class
public class myClass
{
    public int Column1;
    public string Column2;
}
// then
var query = dt.AsEnumerable()
              .Select(row => new myClass
              {
                  Column1 = Convert.ToInt32(row[colsNames[0]]),
                  Column2 = row[colsNames[1]].ToString()
              });

还有第三种变体:您可以在数据库中创建视图或存储过程并将其添加到数据上下文中

【讨论】:

  • 不能 +1。学分不够。为 ChangeType +1。我会尝试在我的解决方案中实现它。
  • 好的,放置+稍后,虽然不一定:)
  • Colum1 = row[0] 就够了,已经输入了。
  • @Boris。我认为该解决方案行不通。如果我这样做query.GetType();,我会得到System.Data.EnumerableRowCollection1[System.Object],但不是System.Data.EnumerableRowCollection1[System.Decimal] 所需的
  • 应该是这样。如果你想要 System.Data.EnumerableRowCollection1[System.Decimal] 你应该写 .Select(row => Convert.ChangeType(row[colsNames[5]], colTypes[colsNames[5]] )),但这不是你想要的, 不是?要获得十进制写: foreach(var q in query) q.Column5 ...
猜你喜欢
  • 2017-08-12
  • 1970-01-01
  • 1970-01-01
  • 2023-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-16
  • 1970-01-01
相关资源
最近更新 更多