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

时间:2014-10-31 13:45:43

标签: c# .net linq datatable lambda

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

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

由于

3 个答案:

答案 0 :(得分:1)

我已经包含了一个与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;
    }

答案 1 :(得分:0)

他们的关键是使用LINQ查询结果作为其Implemented IList接口。 如果您将结果作为IList对象作为参数接收,则可以通过以下方式访问其列和行:

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

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

  1. 步骤1,创建一个名为&#34; GridHelper&#34;的类。 (将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上使用您的DataTable

答案 2 :(得分:0)

查看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