简体   繁体   English

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

[英]How to convert a LINQ query result to a DataTable dynamically?

How to convert a LINQ query result to a DataTable dynamically? 如何将LINQ查询结果动态转换为DataTable?

There are solutions where you create another class and specify the column names, but I want the flexibility to change the LINQ structure like column names, column quantities, and have a DataTable generated with the columns names automatically. 在解决方案中,您可以创建另一个类并指定列名称,但是我希望能够灵活地更改LINQ结构(例如列名称,列数量),并使用列名称自动生成DataTable。

Thanks 谢谢

I've included an extension method that I use with SqlBulkCopy that should do the job, but I'd like to ask why you want to this conversion. 我已经包含了一个与SqlBulkCopy一起使用的扩展方法,该方法可以完成这项工作,但是我想问一下为什么要进行这种转换。 There are a very limited number of cases (SqlBulkCopy being one) where a list of objects can't do everything a datatable can. 在少数情况下(SqlBulkCopy是其中一种情况),对象列表无法完成数据表可以做的所有事情。 You can use them as binding sources for most controls ... just curious. 您可以将它们用作大多数控件的绑定源...很好奇。

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;
    }

They key is to use the LINQ query result as its Implemented IList interface. 他们的关键是将LINQ查询结果用作其Implemented IList接口。 If you receive the result as a parameter on a method as an IList object, you can access its columns and rows, this way: 如果您将结果作为方法的参数作为IList对象接收到,则可以通过以下方式访问其列和行:

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

Refer to this example, it's a small class which please note the it just abstracts the creation of the DataTable, and there is a static method inside called "LINQToDataTable" which you should use. 参考此示例,这是一个小类,请注意它只是抽象了DataTable的创建,并且内部应使用一个称为“ LINQToDataTable”的静态方法。

  1. Step 1, create a class called "GridHelper" (uses System.Data for DataTable structure) 步骤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. Usage: 用法:

      var listaReporte = (from t in dbContext.TablaPruebas select new { Name = t.name, Score = t.score } ) .ToList(); DataTable dt = Library.GridHelper.LINQToDataTable(listaReporte); 
  3. And that is, use your DataTable as you wish, on a GridView or DataGridView 也就是说,根据需要在GridView或DataGridView上使用DataTable

Look into the MoreLinq Nuget package. 查看MoreLinq Nuget软件包。 It has a function ToDataTable() 它具有函数ToDataTable()

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

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

It has other VERY useful functions as well: https://code.google.com/p/morelinq/wiki/OperatorsOverview 它还具有其他非常有用的功能: https : //code.google.com/p/morelinq/wiki/Operators概述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM