0

我目前有一个DataTable以下列:日期,X1,Y1,Z1,X2,Y2,Z2 ... Xn,Yn,Zn。

填充后,Date ALWAYS 有一个值,X/Y/Z1 到 X/Y/Zn 可以是DBNull、 astring或 an int。如果除日期外的整行是 DBNull,我想删除该特定行。

我目前正在进行详尽的搜索,使用 for 循环遍历每一行,然后使用嵌套的 for 循环,检查每个单元格,如果我没有找到任何数据(即只有 dbnull 的),然后我调用 RemoveAt,然后重置外循环再次从零开始。

执行此操作是否有更好/更简单的方法?无法修改数据表的初始构建,这必须是构建后发生的事情。

4

7 回答 7

6

如果我理解正确,如果所有列都有DbNull.Value. 尝试以下方法来做到这一点。

DataTable table = new DataTable();
string[] columns = table.Columns.Cast<DataColumn>()
                                .Select(x => x.ColumnName)
                                .Skip(1)//skip to ignore first column
                                .ToArray();

方法1: 删除所有无效行

var invalidRows = table.AsEnumerable()
    .Where(x => columns.All(c => x.Field<object>(c) == DBNull.Value))
    .ToArray();

foreach (var row in invalidRows)
{
    table.Rows.Remove(row);
}

方法 2:只取有效行并DataTable按照我的 @Tim 在评论中的建议进行新建,以在您有许多无效行时提高性能

var newTable = table.AsEnumerable()
             .Where(x => columns.Any(c => x.Field<object>(c) != DBNull.Value))
             .CopyToDataTable();
于 2013-09-25T11:44:55.880 回答
0

可能这会对你有所帮助。试试这个

    var ordered = yourdatatable.AsEnumerable().Where(x => x.Field<DateTime>("ColumnName") != null);

if (ordered.Count() > 0)
                        {
                            yourdatatable= orderedCopyToDataTable();
                        }

您也可以对其他列执行相同的操作。

或者

为什么不检查查询中的空值。检查ISNULL(columnName, value)作为列名。在此处查看更多详细信息

于 2013-09-25T11:43:16.967 回答
0

注意:这些是我的例子>>不完全适合你的桌子>>>所以自己改变主要帮助在这里>>帮助

然后方法一:

dtData.Select("ID=1 AND ID2=3");

方式二:

GridFieldDAO dao = new GridFieldDAO();
    //Load My DataTable
    DataTable dt = dao.getDT();
    //Get My rows based off selection criteria
    DataRow[] drs = dt.Select("(detailID = 1) AND (detailTypeID = 2)");
    //make a new "results" datatable via clone to keep structure
    DataTable dt2 = dt.Clone();
    //Import the Rows
    foreach (DataRow d in drs)
    {
        dt2.ImportRow(d);
    }
    //Bind to my new DataTable and it will only show rows based off selection 
    //criteria
    myGrid.DataSource = dt2;
    myGrid.DataBind();

最好的方法是:

DataTable tblFiltered = table.AsEnumerable()
      .Where(row => row.Field<String>("Nachname") == username
               &&   row.Field<String>("Ort") == location)
      .OrderByDescending(row => row.Field<String>("Nachname"))
      .CopyToDataTable();
于 2013-09-25T11:46:28.317 回答
0

您可以使用这个小 Linq 查询:

var columnsWithoutDate = table.Columns.Cast<DataColumn>().Skip(1);
table = table.AsEnumerable()
    .Where(row => columnsWithoutDate.Any(col => !row.IsNull(col)))
    .CopyToDataTable();

Skip(1)返回除第一列之外的所有列,因此您的日期列被排除在外。Where枚举表中的所有内容DataRows并获取所有包含至少一个非空字段的行(请参阅:DataRow.IsNull(column))。最后CopyToDataTable创建一个新的DataTable.

于 2013-09-25T11:48:45.357 回答
0

修改后的答案:

myDataTable.AsEnumerable().Where(a => a.ItemArray.Count(b=>b != DBNull.Value)==1).ToList().ForEach(row => dataTable.Rows.Remove(row));

我检查了,它有效。

编辑

回应@Tim Schmelter 评论:

1. 你需要 C# 中的 myDataTable.AsEnumerable()

如果你有一个强类型的 DataTable,你就没有。我认为是这样,因为 OP 说:

无法修改数据表的初始构建,这必须是构建后发生的事情。

也许我不明白他的意思(我的英语有时让我失败)

2. 计算非空字段不正确,因为字符串可以为空,这与 DBNull.Value 不同(也根据 OP 的规范)

你可能是对的。如果 OP 说他只想要 DBNull,则应删除第二个条件(我的一个坏习惯是检查 null 以防万一)

3. ToList 创建另一个 List 是多余的

是的。如果没有 ToList(),就不能使用 ForEach()。可以使用老式的 foreach 代替,或者更好的 for 循环(因为当您尝试修改其中的集合时,foreach 不喜欢)。你仍然必须以某种方式保持你的结果。

4. DataRow.Delete 不会从表中删除所需的内容,但会将其标记为已为 DataAdapter 删除(OP 没有提到他正在使用它,这也是不需要的)。

谢谢你指出这一点。

于 2013-09-25T11:49:17.820 回答
0

您是否尝试过使用 DataTable 的 RowFilter?

DataTable dt = GetData();
//set the filter
dt.DefaultView.RowFilter = "----your filter----";
//then access the DataView
foreach (DataRowView drv in dt.DefaultView)
{
            //you can also get a row from rowview
            DataRow dr = drv.Row;
}

查看此文档,他们还解释了如何处理过滤器中的空值。

http://msdn.microsoft.com/en-us/library/system.data.dataview.rowfilter.aspx

您也可以使用具有相同过滤器的 Select() 方法,请参阅下面的答案,这两种方法都有很好的比较。

DataView.RowFilter 与 DataTable.Select() 与 DataTable.Rows.Find()

我不建议使用AsEnumerable()方法,虽然看起来像简单的代码,但它就像在行上执行一个 foreach 循环并具有 IF 条件。

DataTable 过滤器方法应该比AsEnumerable()更快(我不确定,但我假设这是因为 DataTable 是 .net 处理表格数据的强大数据结构)

于 2013-09-25T11:57:29.423 回答
0

我会去做这样的事情:

        var test = from row in table.AsEnumerable()
                   where (!row.IsNull("col1") || !row.IsNull("col2"))
                   select row;

        //option1
        DataTable dt = test.CopyToDataTable<DataRow>();

        //option2
        DataTable dt2 = new DataTable();
        dt2.Columns.Add("col1", typeof(String));
        dt2.Columns.Add("col2", typeof(Int32));

        foreach (var v in test)
        {
            DataRow dr = dt2.NewRow();
            dr["col1"] = v.Field<String>("col1");
            dr["col1"] = v.Field<Int32>("col2");
            dt2.Rows.Add(dr);
        }
于 2013-09-25T12:00:18.697 回答