如何动态地将LINQ查询结果转换为DataTable?

如何动态地将LINQ查询结果转换为DataTable?

问题描述:

如何动态地将LINQ查询结果转换为DataTable?如何动态地将LINQ查询结果转换为DataTable?

有些解决方案可以创建另一个类并指定列名,但我希望能够灵活地更改LINQ结构(如列名,列数),并自动生成带有列名的DataTable。

感谢

我已经包含了一个扩展方法,我使用SqlBulkCopy来完成这个工作,但是我想问你为什么要这个转换。数量有限的情况下(SqlBulkCopy是一个),其中一个对象列表不能做一切数据表可以。您可以将它们用作大多数控件的绑定源......只是好奇。

public static DataTable toDataTable<T>(this IEnumerable<T> value, List<string> exclusionList) 
     where T : class 
    { 
     var dataTable = new DataTable(); 

     var type = typeof(T); 

     var properties = type.GetProperties().Where(x => !exclusionList.Contains(x.Name)).ToList(); 

     foreach (var propertyInfo in properties) 
     { 
      var propertyType = propertyInfo.PropertyType; 
      if (!propertyType.IsScalar()) 
       continue; 

      var nullableType = Nullable.GetUnderlyingType(propertyType); 
      propertyType = nullableType ?? propertyType; 

      var dataColumn = new DataColumn(propertyInfo.Name, propertyType); 

      if (nullableType != null) 
       dataColumn.AllowDBNull = true; 

      dataTable.Columns.Add(dataColumn); 
     } 

     foreach (var row in value) 
     { 
      var dataRow = dataTable.NewRow(); 

      foreach (var property in properties) 
      { 
       var safeValue = property.GetValue(row, null) ?? DBNull.Value;      
       dataRow[property.Name] = safeValue; 
      } 

      dataTable.Rows.Add(dataRow); 
     } 

     return dataTable; 
    } 
+0

让我们假设你有一个图书馆一类检索使用LINQ从数据库中的信息,您想要返回不同类型的项目,如Windows Form(DataGridView),Web Form(GridView)等可以显示信息的结果,您不能返回Anonymous类型的列表。我试图使用你的扩展,但我不知道IsScalar()是在哪里声明的。 – 2014-10-31 16:57:02

+0

标量是在另一个库中,你可以把它拉出来 – 2014-10-31 17:03:07

他们关键是使用LINQ查询结果作为其实现IList接口。 如果您收到的结果作为一个参数上的方法作为一个IList对象,你可以访问它的行和列,这样说:

var props = item.GetType().GetProperties(); 

参考这个例子中,它是一个小类请你只注意它抽象DataTable的创建,并且里面有一个叫做“LINQToDataTable”的静态方法,你应该使用它。

  1. 步骤1,创建一个名为 “GridHelper” 类(使用System.Data DataTable的用于结构)

    public class GridHelper 
    { 
    private DataTable baseDt; 
    
    public GridHelper(string tableName) 
    { 
        baseDt = new DataTable(tableName); 
    } 
    
    
    public DataTable getDataTable() 
    { 
        return baseDt; 
    } 
    
    public object[,] getObjToFill() 
    { 
        object[,] obj = new object[baseDt.Columns.Count, 2]; 
        for (int i = 0; i < baseDt.Columns.Count; i++) 
        { 
         obj[i, 0] = baseDt.Columns[i].ColumnName; 
        } 
    
        return obj; 
    } 
    
    public void addColumn(string colName, Type valueType) 
    { 
        baseDt.Columns.Add(colName, valueType); 
    } 
    
    public void addRow(object[,] values) 
    { 
    
        DataRow newRow = baseDt.NewRow(); 
    
        for (int i = 0; i < values.Length/2; i++) 
        { 
         bool colFound = false; 
    
         for (int j = 0; j < baseDt.Columns.Count; j++) 
         { 
          if (baseDt.Columns[j].ColumnName == values[i, 0].ToString()) 
          { 
           colFound = true; 
           break; 
          } 
         } 
         if (colFound == false) 
         { 
          throw new Exception("The column " + values[i, 0].ToString() + " has not been added yet."); 
         } 
    
         newRow[values[i, 0].ToString()] = values[i, 1]; 
        } 
    
        baseDt.Rows.Add(newRow); 
    
    } 
    
    
    public static DataTable LINQToDataTable<T>(T objToList) where T : System.Collections.IList 
    { 
    
    
        GridHelper ghResult = new GridHelper("Report"); 
    
    
        foreach (Object item in objToList) 
        { 
         var props = item.GetType().GetProperties(); 
    
         foreach (var prop in props) 
         { 
          ghResult.addColumn(prop.Name, typeof(string)); 
          //prop.Name 
          //prop.GetValue(item) 
         } 
    
         break; 
        } 
    
        object[,] obj = ghResult.getObjToFill(); 
    
    
    
    
        foreach (Object item in objToList) 
        { 
         var props = item.GetType().GetProperties(); 
         int index = 0; 
         foreach (var prop in props) 
         { 
          //ReportValue(prop.Name, prop.GetValue(item, null)); 
          //prop.Name 
          obj[index, 1] = prop.GetValue(item); 
          index++; 
         } 
    
         ghResult.addRow(obj); 
        } 
    
    
        return ghResult.getDataTable(); 
    } 
    
    
    
    } 
    
  2. 用法:

    var listaReporte = 
         (from t in dbContext.TablaPruebas 
         select new 
         { 
          Name = t.name, 
          Score = t.score 
         } 
         ) .ToList(); 
    
        DataTable dt = Library.GridHelper.LINQToDataTable(listaReporte); 
    
  3. ,那就是,用你的数据表如您所愿,在GridView或DataGridView上

查看MoreLinq Nuget包。它有一个功能ToDataTable()

var LinqResults = from ......; 
DataTable dt_Results = LinqResults.ToDataTable(); 

https://code.google.com/p/morelinq/

它具有其他非常有用的功能,以及: https://code.google.com/p/morelinq/wiki/OperatorsOverview