如何有效地验证大量列

时间:2017-04-06 04:19:22

标签: c#

我有一个下面的DataTable,它可以有任意数量的行,每行中的列大约是40。 我正在尝试验证每个列,如果它无法在新表中复制该行。

private void ValidateRows(DataTable csvDataTable)
{
    DataTable invalidatedTable = new DataTable();
    invalidatedTable = csvDataTable.Clone();

    // Loop over all the rows in the datatable
    foreach (DataRow row in csvDataTable.Rows)
    {
        bool invalidated = false;

        if (row["ID"].ToString() == "")
        {
            invalidated = true;
            row["ID"] = "not valid";
        }
        if (row["Name"].ToString() != "test")
        {
            invalidated = true;
        }
        //and rest of the validation

        //if invalid
        if (invalidated)
        {           
            invalidatedTable.Rows.Add(row.ItemArray);
        }
    } // End Loop  
}

如果有一种有效的方法可以进行验证吗? 我们可以申请哪种模式来验证看起来更干净的行吗?

由于

3 个答案:

答案 0 :(得分:0)

您可以在不使用布尔变量的情况下自动添加无效记录:

foreach (DataRow row in csvDataTable.Rows)
        {
            if (row["ID"].ToString() == "" || row["Name"].ToString() != "test")
            {
                invalidatedTable.Rows.Add(row.ItemArray);
                if (row["ID"].ToString() == "") 
                    row["ID"] = "not valid";
            }
        }

这看起来更干净,更易读。

答案 1 :(得分:0)

您正在检查每一列,即使某些早期列已使该行无效。如果您期望大量无效行,那么这将显着影响您的表现。

如果检查没有副作用(如Name检查),请随意跳过。

if (!invalidated && row["Name"].ToString() != "test")
{
    invalidated = true;
}

如果没有关于行无效的更多细节,我不确定你能做的还有更多。

答案 2 :(得分:0)

如果您的大多数验证条件都很简单(并且没有副作用),您可以将每个条件存储为委托,然后循环遍历它们。

private void ValidateRows(DataTable csvDataTable)
{
    DataTable invalidatedTable = new DataTable();
    invalidatedTable = csvDataTable.Clone();

    List<Func<DataRow, bool>> validators = new List<Func<DataRow, bool>>
    {
        row => row["ID"].ToString() == "",
        row => row["Name"].ToString() != "test",
    };

    // Loop over all the rows in the datatable
    foreach (DataRow row in csvDataTable.Rows)
    {
        bool valid = validators.All(validator => validator(row));
        if (!valid)
        {
            invalidatedTable.Rows.Add(row.ItemArray);
        }

    } // End Loop  
}

每个验证方法都成为validators列表中的一个附加条目。

(请注意,对validators.All的调用是短路的 - 只要其中一个验证失败,就不会为该特定行运行其他任何验证。)

这种方法的缺点是,为特定验证执行副作用(例如在原始代码中设置row["ID"] = "not valid")会变得很麻烦。您要么需要增强委托,而不仅仅是单行,如下所示:

List<Func<DataRow, bool>> validators = new List<Func<DataRow, bool>>
{
    row =>
    {
        bool idIsEmpty = row["ID"].ToString() == "";
        if (idIsEmpty) row["ID"] = "not valid";
        return !idIsEmpty;
    },
    row => row["Name"].ToString() != "test",
};

或将这些案例分解为单独的函数:

List<Func<DataRow, bool>> validators = new List<Func<DataRow, bool>>
{
    RowIdValidation,
    row => row["Name"].ToString() != "test",
};

... snip ...

private static bool RowIdValidation(DataRow row)
{
    bool idIsEmpty = row["ID"].ToString() == "";
    if (idIsEmpty) row["ID"] = "not valid";
    return !idIsEmpty;
}

此外(如@MotKohn所述),您需要修改代码以防止All的短路行为导致跳过副作用,可能是通过使用普通的foreach循环代替。

TL; DR - 如果您在验证后发生副作用,切换到此样式可能会使您的代码 lot 更难以遵循。