C# DataRow пустой-проверка

у меня есть это:

 DataTable dtEntity = CreateDataTable();
 drEntity = dtEntity.NewRow();

затем я добавляю данные в строку (или нет). Много кода, правда, не знаю, есть ли что-нибудь внутри строки. Зависит от ввода (я импортирую из некоторых файлов). Я хотел бы сделать что-то вроде:

 if (drEntity`s EVERY CELL IS NOT EMPTY)
 {
   dtEntity.Rows.Add(drEntity);
 }
 else
 {
   //don't add, will create a new one (drEntity = dtEntity.NewRow();)
 }

есть ли хороший способ проверить, пуста ли каждая ячейка DataRow? Или я должен foreach, и проверить их один за другим?

10 ответов


простой метод по строкам:

bool AreAllColumnsEmpty(DataRow dr)
{
 if (dr == null)
 {
  return true;
 }
 else
 {
  foreach(var value in dr.ItemArray)
  {
    if (value != null)
    {
      return false;
    }
  }
  return true;
 }
}

должен дать вам то, что вам нужно, и сделать его "хорошим" (поскольку, насколько мне известно, в рамках ничего нет), вы можете обернуть его как метод расширения, и тогда ваш результирующий код будет:

if (datarow.AreAllColumnsEmpty())
{
}
else
{
}

Я создал помощника (в статическом классе я назвал DataRowHelpers, изобретательный, я знаю) называется IsEmpty следующим образом:

public static bool IsEmpty(this DataRow row)
{
    return row == null || row.ItemArray.All(i => i is DBNull);
}

другие ответы здесь верны. Я просто почувствовал, что моя краткость в кратком использовании Linq для объектов. Кстати, это действительно полезно в сочетании с синтаксическим анализом Excel, поскольку пользователи могут прикреплять строку вниз по странице (тысячи строк) без учета того, как это влияет на анализ данных.

в том же классе я поставил любых других помощников, которых я нашел полезно, как Парсеры, так что если поле содержит текст, который, как вы знаете, должен быть числом, вы можете анализировать его свободно. Незначительный совет для любой новой идеи. (Кто на так на самом деле? Неее!)

имея это в виду, вот Расширенная версия:

public static bool IsEmpty(this DataRow row)
{
    return row == null || row.ItemArray.All(i => i.IsNullEquivalent());
}

public static bool IsNullEquivalent(this object value)
{
    return value == null
           || value is DBNull
           || string.IsNullOrWhiteSpace(value.ToString());
}

теперь у вас есть еще один полезный помощник, IsNullEquivalent который можно использовать в этом контексте и в любом другом тоже. Вы можете расширить это, чтобы включить такие вещи, как "n/a" или "TBD" если вы знаете, что ваши данные имеют заполнители, как что.


Я предпочитаю подход Томми Карлье, но с небольшим изменением.

foreach (DataColumn column in row.Table.Columns)
    if (!row.IsNull(column))
      return false;

  return true;

Я полагаю, что такой подход выглядит более простым и ярким.


public static bool AreAllCellsEmpty(DataRow row)
{
  if (row == null) throw new ArgumentNullException("row");

  for (int i = row.Table.Columns.Count - 1; i >= 0; i--)
    if (!row.IsNull(i))
      return false;

  return true;
}

Я знаю, что на это уже ответили, и это старый вопрос, но вот метод расширения, чтобы сделать то же самое:

public static class DataExtensions
{
    public static bool AreAllCellsEmpty(this DataRow row)
    {
        var itemArray = row.ItemArray;
        if(itemArray==null)
            return true;
        return itemArray.All(x => string.IsNullOrWhiteSpace(x.ToString()));            
    }
}

и вы используете его так:

if (dr.AreAllCellsEmpty())
// etc

вы можете использовать этот:

if(drEntity.ItemArray.Where(c => IsNotEmpty(c)).ToArray().Length == 0)
{
    // Row is empty
}

IsNotEmpty(cell) будет вашей собственной реализацией, проверяющей, являются ли данные нулевыми или пустыми, на основе того, какой тип данных находится в ячейке. Если это простая строка, она может выглядеть примерно так:

if(drEntity.ItemArray.Where(c => c != null && !c.Equals("")).ToArray().Length == 0)
{
    // Row is empty
}
else
{
    // Row is not empty
}

тем не менее, он по существу проверяет каждую ячейку на пустоту и позволяет узнать, все ли ячейки в строке пусты.


DataTable.NewRow инициализирует каждое поле:

  • значение по умолчанию для каждого DataColumn (DataColumn.DefaultValue)

  • кроме авто-инкремент колонки (DataColumn.AutoIncrement == true), который будет инициализирован до следующего значения автоматического приращения.

  • и столбцы выражений (DataColumn.Expression.Length > 0) также являются частным случаем; значение по умолчанию будет зависеть от значений по умолчанию столбцов, на которых выражение рассчитанный.

так что вы, вероятно, должны проверять что-то вроде:

bool isDirty = false;
for (int i=0; i<table.Columns.Count; i++)
{
    if (table.Columns[i].Expression.Length > 0) continue;
    if (table.Columns[i].AutoIncrement) continue;
    if (row[i] != table.Columns[i].DefaultValue) isDirty = true;
}

Я оставлю версию LINQ в качестве упражнения:)


AFAIK, нет метода,который делает это в рамках. Даже если бы в рамках была поддержка чего-то подобного, это, по сути, делало бы то же самое. И это будет смотреть на каждую ячейку в DataRow, чтобы увидеть, пуста ли она.


Я сделал это так:

var listOfRows = new List<DataRow>();
foreach (var row in resultTable.Rows.Cast<DataRow>())
{
    var isEmpty = row.ItemArray.All(x => x == null || (x!= null && string.IsNullOrWhiteSpace(x.ToString())));
    if (!isEmpty)
    {
        listOfRows.Add(row);
    }
}

возможно, лучшим решением было бы добавить дополнительный столбец, который автоматически устанавливается в 1 в каждой строке. Как только есть элемент, который не является нулевым, измените его на 0.

затем

If(drEntitity.rows[i].coulmn[8] = 1)
{
   dtEntity.Rows.Add(drEntity);
}
 else
 {
   //don't add, will create a new one (drEntity = dtEntity.NewRow();)
 }