4

是否可以在 C# 中的 DataTable 上创建值范围约束?

我正在向 DataTable 动态添加一列:

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

但我希望此列中的所有值都是 [0, 10] 中的整数。我可以直接在 DataTable 上实现这样的约束吗?

我能想到的下一个最佳选择是创建一些具有可能值 [0, 10] 的对象,而不是 typeof(int),使用 typeof(specialObj)。

4

3 回答 3

7

一种方法是检查e.ProposedValueDataTable 的 ColumnChanging 事件。

要对特定列进行约束,可以使用 DataColumn 的 ExtendedProperties 集合作为标志来检查这些约束:

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;
  }
}
于 2013-11-20T14:51:52.037 回答
2

我可以建议您忘记数据表并使用类。您可以使用数据注释来验证您的模型。

使用此属性验证特定属性的一系列值/

此代码摘自指定文章(验证范围的类示例):

public class Product
{

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

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

}

你会发现使用类有很多好处。

于 2013-11-21T02:21:01.070 回答
0

这是一篇旧文章,但我正在使用一种解决方案来同步未由OleDbDataAdapter.FillSchema填充的 Check_Constraints值得一提的 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);
    }
}
于 2017-09-19T21:25:07.410 回答