簡體   English   中英

我如何添加linq查詢EnumerableRowCollection <TRow> 到數據表?

[英]How can i add linq query EnumerableRowCollection<TRow> to a datatable?

我有這個linq查詢:

 var lastDaysData = from myRow in rawDataSet.AsEnumerable()
                            where myRow.Field<DateTime>("DateTime") < DateTime.Now.AddHours(-24)
                            select myRow;

我認為應該從SQL數據庫返回最后24小時的數據。

我試圖查詢的結果添加到datatableforeach循環:

 DataTable dataTable = new DataTable();

            foreach (DataRow row in lastDaysData)
            {
                dataTable.ImportRow(row);
            }

            dataGridView1.DataSource = dataTable;

但是,我的datagridview沒有填充任何數據。

所以,我在加入行不正確的datatable或者是我的LINQ查詢錯了嗎?

最后我自己弄清楚了。

我必須先將想要的列添加到List ,然后再將列表添加到dataTable

     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;

大多數時候,我會說您不應該在現代C#中使用DataTable ,您應該使用EF或LINQ進行SQL並直接使用對象。

但是,當我必須與他們合作時,我使用一些擴展方法來使LINQ與DataTable一起使用更容易。

這將從DataTable.AsEnumerable()上的LINQ查詢中將所得IEnumerable<DataRow>轉換為具有匹配模式的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;
}

這讓我們使用匿名對象選擇列,然后從這些對象創建一個新的DataTable ,但是它使用反射,因此速度很慢。 最好對上面的ToDataTable進行變體,使其采用列名列表,以相應地ToDataTable答案。

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

您需要一些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);

最后,如果跨多個DataTable ,則可以使用以下方法將答案展平到另一個DataTable

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM