C# DataTable 中 DataColumn 的约束是什么?

4

在C#中,能否为DataTable创建一个值范围约束?

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

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

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

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


相关系数的范围肯定是区间[-1, 1],对吧? - Colonel Panic
3个回答

7

一种方法是在DataTable的ColumnChanging事件中检查e.ProposedValue

如果要对特定列进行约束,则可以使用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;
  }
}

很酷。是否有可能拒绝更改并恢复旧值? - Colonel Panic
@ColonelPanic 你可以选择抛出异常,或者触发自己的事件,或者将初始的e.ProposedValue存储在一个变量中以便稍后还原。我的示例代码只是将值恢复到了我添加的Min-Max属性范围内。 - LarsTech

2

我建议您放弃使用数据表格,改用类。您可以使用数据注释来验证您的模型。

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

以下代码摘自指定文章(一个进行范围验证的类的示例):

public class Product
{

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

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

}

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

1
最后,我也放弃了数据表。在我的情况下,由于我使用DataTable来处理数据库中的表格,我只需在数据库中的表格上创建约束即可。但我想有些情况下你可能仍需要使用数据表。 - Rafael Emshoff

0

这是一篇旧帖子,但我正在使用一种解决方案来同步由OleDbDataAdapter.FillSchema在Access数据库中未填充的Check_Constraints,值得一提。只需使用OleDbConnection检索GetOleDbSchemaTable,然后使用foreach()循环遍历行,提取验证文本表达式并创建一个匿名delegate,附加到适当的表和列上的Table.ColumnChanging事件。然后,通过方便的Eval()函数动态评估由Access模式提供的字符串验证,详细描述请参见here。以下是我的代码:

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);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接