C# 如何将linq查询EnumerablerRowCollection添加到数据表?

C# 如何将linq查询EnumerablerRowCollection添加到数据表?,c#,linq,C#,Linq,我有一个linq查询: 但是,我的datagridview没有填充任何数据 那么,我是否将行错误地添加到数据表中,或者我的linq查询是否错误 最后我自己弄明白了 我必须先将我想要的列添加到列表中,然后将列表添加到数据表中 大多数时候,我想说的是,在现代C语言中不应该使用DataTables,应该使用EF或LINQ来SQL并直接使用对象 但是,当我必须使用它们时,我使用一些扩展方法使LINQ与数据表的使用变得更容易 此操作将从DataTable.AsEnumerable上的LINQ查询生成的IE

我有一个linq查询:

但是,我的datagridview没有填充任何数据


那么,我是否将行错误地添加到数据表中,或者我的linq查询是否错误

最后我自己弄明白了

我必须先将我想要的列添加到列表中,然后将列表添加到数据表中


大多数时候,我想说的是,在现代C语言中不应该使用DataTables,应该使用EF或LINQ来SQL并直接使用对象

但是,当我必须使用它们时,我使用一些扩展方法使LINQ与数据表的使用变得更容易

此操作将从DataTable.AsEnumerable上的LINQ查询生成的IEnumerable转换回具有匹配架构的DataTable:

public static DataTable ToDataTable(this IEnumerable<DataRow> src) {
    var ans = src.First().Table.Clone();
    foreach (var r in src)
        ans.ImportRow(r);
    return ans;
}
您需要一些MemberInfo扩展,以便更轻松地使用属性和字段:

// ***
// *** Type Extensions
// ***
public static List<MemberInfo> GetPropertiesOrFields(this Type t, BindingFlags bf = BindingFlags.Public | BindingFlags.Instance) =>
    t.GetMembers(bf).Where(mi => mi.MemberType == MemberTypes.Field | mi.MemberType == MemberTypes.Property).ToList();

// ***
// *** MemberInfo Extensions
// ***
public static Type GetMemberType(this MemberInfo member) {
    switch (member) {
        case FieldInfo mfi:
            return mfi.FieldType;
        case PropertyInfo mpi:
            return mpi.PropertyType;
        case EventInfo mei:
            return mei.EventHandlerType;
        default:
            throw new ArgumentException("MemberInfo must be if type FieldInfo, PropertyInfo or EventInfo", nameof(member));
    }
}

public static object GetValue(this MemberInfo member, object srcObject) {
    switch (member) {
        case FieldInfo mfi:
            return mfi.GetValue(srcObject);
        case PropertyInfo mpi:
            return mpi.GetValue(srcObject);
        default:
            throw new ArgumentException("MemberInfo must be of type FieldInfo or PropertyInfo", nameof(member));
    }
}
public static T GetValue<T>(this MemberInfo member, object srcObject) => (T)member.GetValue(srcObject);

请检查您的查询是否返回任何记录。看起来您的查询是错误的,因为它返回的记录早于24小时,而不是过去的24小时。当您将break放入循环中时,调试器会说什么?是否出现异常?可能您在一个空的catch中吞下了异常,应该从SQL数据库返回过去24小时的数据,因为DataTable是内存中的集合,它没有链接到SQL数据库。也许您认为它会从数据库中查询行,但事实并非如此。那么你需要一个SqlDataAdapter。@Wokuo啊哈,我不确定是否是这样,但即使如此,仍然有很多数据超过24小时,所以它仍然应该返回数据。我将检查将ToList与newlist一起使用没有任何好处-您应该在lastDaysData中的每个var项上循环lastDaysData-您只是在浪费内存和时间构建一个立即枚举的列表。扁平化的用例是什么。我不确定这个程序做什么。Thanks@kuklei如果您使用LINQ连接两个数据表,它将把包含来自不同表的数据行的匿名对象转换成一个新的数据表。
     var rawDataSet = pDCDataSet.RawData;

        var lastDaysData = from myRow in rawDataSet.AsEnumerable()
                           where myRow.Field<DateTime>("DateTime") > DateTime.Now.AddHours(-Convert.ToInt32(comboBox1.Text))
                           select new
                           {
                               myRow.DateTime,
                               myRow.FolderSize,
                               myRow.FileNumber,
                               //myRow.Results,
                           };

       var newlist = lastDaysData.ToList();

        DataTable dt = new DataTable();

        dt.Columns.Add("DateTime");
        dt.Columns.Add("FolderSize");
        dt.Columns.Add("FileNumber");
        foreach (var item in newlist)
        {
            var row = dt.NewRow();

            row["DateTime"] = item.DateTime;
            row["FolderSize"] = Convert.ToString(item.FolderSize);
            row["FileNumber"] = item.FileNumber;

            dt.Rows.Add(row);
        }


        dataGridView1.DataSource = dt;
public static DataTable ToDataTable(this IEnumerable<DataRow> src) {
    var ans = src.First().Table.Clone();
    foreach (var r in src)
        ans.ImportRow(r);
    return ans;
}
public static DataTable ToDataTable<T>(this IEnumerable<T> rows) {
    var dt = new DataTable();
    if (rows.Any()) {
        var rowType = typeof(T);
        var memberInfos = rowType.GetPropertiesOrFields();
        foreach (var info in memberInfos)
            dt.Columns.Add(new DataColumn(info.Name, info.GetMemberType()));

        foreach (var r in rows)
            dt.Rows.Add(memberInfos.Select(i => i.GetValue(r)).ToArray());
    }
    return dt;
}
// ***
// *** Type Extensions
// ***
public static List<MemberInfo> GetPropertiesOrFields(this Type t, BindingFlags bf = BindingFlags.Public | BindingFlags.Instance) =>
    t.GetMembers(bf).Where(mi => mi.MemberType == MemberTypes.Field | mi.MemberType == MemberTypes.Property).ToList();

// ***
// *** MemberInfo Extensions
// ***
public static Type GetMemberType(this MemberInfo member) {
    switch (member) {
        case FieldInfo mfi:
            return mfi.FieldType;
        case PropertyInfo mpi:
            return mpi.PropertyType;
        case EventInfo mei:
            return mei.EventHandlerType;
        default:
            throw new ArgumentException("MemberInfo must be if type FieldInfo, PropertyInfo or EventInfo", nameof(member));
    }
}

public static object GetValue(this MemberInfo member, object srcObject) {
    switch (member) {
        case FieldInfo mfi:
            return mfi.GetValue(srcObject);
        case PropertyInfo mpi:
            return mpi.GetValue(srcObject);
        default:
            throw new ArgumentException("MemberInfo must be of type FieldInfo or PropertyInfo", nameof(member));
    }
}
public static T GetValue<T>(this MemberInfo member, object srcObject) => (T)member.GetValue(srcObject);
// Create new DataTable from LINQ results on DataTable
// Expect T to be anonymous object of form new { DataRow d1, DataRow d2, ... }
public static DataTable FlattenToDataTable<T>(this IEnumerable<T> src) {
    var res = new DataTable();
    if (src.Any()) {
        var firstRow = src.First();
        var rowType = typeof(T);
        var memberInfos = rowType.GetPropertiesOrFields();
        var allDC = memberInfos.SelectMany(mi => mi.GetValue<DataRow>(firstRow).Table.DataColumns());

        foreach (var dc in allDC) {
            var newColumnName = dc.ColumnName;
            if (res.ColumnNames().Contains(newColumnName)) {
                var suffixNumber = 1;
                while (res.ColumnNames().Contains($"{newColumnName}.{suffixNumber}"))
                    ++suffixNumber;
                newColumnName = $"{newColumnName}.{suffixNumber}";
            }
            res.Columns.Add(new DataColumn(newColumnName, dc.DataType));
        }

        foreach (var objRows in src)
            res.Rows.Add(memberInfos.SelectMany(mi => mi.GetValue<DataRow>(objRows).ItemArray).ToArray());
    }
    return res;
}