Ограничение на DataColumn в С# DataTable?

Можно ли создать ограничение диапазона значений для DataTable в C#?

Я динамически добавляю столбец в DataTable:

this.PrimaryCorrelationMatrix.Columns.Add(sName, typeof(int));

но я бы хотел, чтобы все значения в этом столбце были целыми числами от [0, 10]. Могу ли я реализовать такое ограничение непосредственно в DataTable?

Следующий лучший вариант, который я могу придумать, это создать некий объект с возможными значениями [0, 10] и вместо typeof(int) использовать typeof(specialObj).


person Rafael Emshoff    schedule 07.03.2013    source источник
comment
Конечно, диапазон коэффициентов корреляции - это интервал [-1, 1]?   -  person Colonel Panic    schedule 20.11.2013


Ответы (3)


Один из способов сделать это — проверить e.ProposedValue в событии ColumnChanging таблицы данных.

Чтобы иметь ограничение для определенного столбца, вы можете использовать коллекцию ExtendedProperties DataColumn, чтобы действовать как ваш флаг для проверки этих ограничений:

DataTable dt = new DataTable();
DataColumn dc = new DataColumn("Range", typeof(int));
dc.ExtendedProperties.Add("Min", 0);
dc.ExtendedProperties.Add("Max", 10);
dt.Columns.Add(dc);
dt.ColumnChanging += dt_ColumnChanging;

В событии ColumnChanging вы должны проверить, существуют ли эти свойства, а затем использовать их:

void dt_ColumnChanging(object sender, DataColumnChangeEventArgs e) {
  if (e.Column.ExtendedProperties.ContainsKey("Min") &&
      e.Column.ExtendedProperties.ContainsKey("Max")) {
    int min = (int)e.Column.ExtendedProperties["Min"];
    int max = (int)e.Column.ExtendedProperties["Max"];
    if ((int)e.ProposedValue < min) e.ProposedValue = min;
    if ((int)e.ProposedValue > max) e.ProposedValue = max;
  }
}
person LarsTech    schedule 20.11.2013
comment
Это круто. Можно ли отказаться от изменения и вернуться к старому значению? - person Colonel Panic; 20.11.2013
comment
@ColonelPanic Вместо этого вы можете вызвать исключение или собственное событие или сохранить исходное e.ProposedValue в переменной, чтобы вы могли вернуться позже. Мой пример кода просто вернул значение в диапазон добавленных мною свойств Min-Max. - person LarsTech; 20.11.2013

Я могу порекомендовать вам забыть о таблицах данных и использовать классы. Вы можете использовать аннотацию данных для проверки вашей модели.

Используйте этот атрибут для проверки диапазона значений для определенного свойства/

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

public class Product
{

  [Range(5, 50)]
  public int ReorderLevel { get; set; }

  [Range(typeof(Decimal),"5", "5000")]
  public decimal ListPrice { get; set; }

}

Вы найдете много преимуществ в использовании классов.

person Juan    schedule 21.11.2013
comment
В конце концов я тоже отошел от таблиц данных. В моем случае, поскольку я использовал DataTable для работы с таблицей в базе данных, я просто создал ограничение для таблицы в базе данных. Но я предполагаю, что есть некоторые ситуации, когда вы хотели бы придерживаться таблиц данных. - person Rafael Emshoff; 21.11.2013

Это старый пост, но я использую решение для синхронизации Check_Constraints, НЕ заполненное OleDbDataAdapter.FillSchema в базах данных Access, о которых стоит упомянуть. Только что использовал OleDbConnection для получения GetOleDbSchemaTable и foreach() строки, извлекающие текстовое выражение проверки и создающие анонимный делегировать соответствующую таблицу и столбец, прикрепленные к соответствующему событию Table.ColumnChanging. Проверка строки, предоставляемая схемой Access, затем будет динамически оцениваться удобной Eval() описана здесь. Вот мой код:

DataTable schemaTable = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Check_Constraints, null);
// Attach delegate Eval() of each Check_Constraints on proper Table/Column
foreach (DataRow myField in schemaTable.Rows)
{
    string constraint_name = "";
    string check_clause = "";
    foreach (DataColumn myProperty in schemaTable.Columns)
    {
        if (myProperty.ColumnName == "CONSTRAINT_NAME")
            constraint_name = myField[myProperty.ColumnName].ToString();
        if (myProperty.ColumnName == "CHECK_CLAUSE")
            check_clause = myField[myProperty.ColumnName].ToString();
    }
    var rule = constraint_name.Replace("[", "").Replace("]", "").Split('.');
    if (rule.Length == 3 && dataset.Tables.Contains(rule[0]) && dataset.Tables[rule[0]].Columns.Contains(rule[1]) && String.IsNullOrEmpty(check_clause) == false)
    {
        dataset.Tables[rule[0]].ColumnChanging += delegate (object sender, DataColumnChangeEventArgs e)
        {
            if (e.Column.ColumnName == rule[1] && Convert.ToBoolean(ToolBox.Eval(e.ProposedValue + check_clause)) == false)
            {
                throw new Exception("Tabela: " + rule[0] + ", coluna: " + rule[0] + ", cheque: " + check_clause);
            }
        };
        Debug.WriteLine(rule[0] + "." + rule[1] + ": " + check_clause);
    }
}
person macedo123    schedule 19.09.2017