【发布时间】:2014-10-31 13:45:42
【问题描述】:
如何将 LINQ 查询结果动态转换为 DataTable?
有一些解决方案,您可以创建另一个类并指定列名,但我希望能够灵活地更改 LINQ 结构,例如列名、列数量,并使用列名自动生成 DataTable。
谢谢
【问题讨论】:
标签: c# .net linq datatable lambda
如何将 LINQ 查询结果动态转换为 DataTable?
有一些解决方案,您可以创建另一个类并指定列名,但我希望能够灵活地更改 LINQ 结构,例如列名、列数量,并使用列名自动生成 DataTable。
谢谢
【问题讨论】:
标签: c# .net linq datatable lambda
我已经包含了一个与 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;
}
【讨论】:
查看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
【讨论】:
他们的关键是使用 LINQ 查询结果作为其实现的 IList 接口。 如果您将结果作为 IList 对象的方法的参数接收,则可以通过以下方式访问其列和行:
var props = item.GetType().GetProperties();
参考这个例子,它是一个小类,请注意它只是抽象了DataTable的创建,并且里面有一个名为“LINQToDataTable”的静态方法,你应该使用它。
第一步,创建一个名为“GridHelper”的类(DataTable结构使用System.Data)
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();
}
}
用法:
var listaReporte =
(from t in dbContext.TablaPruebas
select new
{
Name = t.name,
Score = t.score
}
) .ToList();
DataTable dt = Library.GridHelper.LINQToDataTable(listaReporte);
也就是说,在 GridView 或 DataGridView 上随意使用 DataTable
【讨论】: