【问题标题】:EnforceConstraint on Datatable对数据表执行约束
【发布时间】:2011-06-22 12:21:16
【问题描述】:

数据集上有一个 EnforceConstraints 属性,指示是否应启用约束。虽然数据表也可以有约束,但我不能禁用数据表的约束。

我的情况是我在内存中使用的数据表在其中一列上具有唯一约束。有时我想暂时禁用唯一约束。我怎样才能做到这一点?我想出的唯一方法是删除并重新添加约束。有没有更好的办法?

【问题讨论】:

    标签: c# datatable strongly-typed-dataset constraints


    【解决方案1】:

    我的解决办法是这样的

    using (IDataReader reader = ExecuteReader(sql))
                {
                    DataTable dt = new DataTable();
                    using (DataSet ds = new DataSet() { EnforceConstraints = false })
                    {
                        ds.Tables.Add(dt);
                        dt.Load(reader, LoadOption.OverwriteChanges);
                        ds.Tables.Remove(dt);
                    }
                    return dt;
                }
    

    【讨论】:

    • 这对我有用,只在使用 mysql 连接器时遇到过这个问题。浏览了很多线程,但只有这个解决了它,因为我正在调用“SHOW PROCESSLIST”所以无法控制输出
    【解决方案2】:

    DataTable 上没有公共 EnforceConstraints 属性。我建议使用以下方法之一来禁用约束:

    • 要暂时禁用约束,请使用DataTable.BeginLoadData() 方法,然后使用DataTable.EndLoadData() 重新启用它们。
    • 将该 DataTable 添加到(虚拟)DataSet 并将属性 DataSet.EnforceConstraints 设置为 false。

    注意:禁用检查约束也会禁用检查有关 DataColumn.AllowDBNullDataColumn.MaxLength 的值。

    【讨论】:

      【解决方案3】:

      基本上我所做的是遍历约束并删除它们。执行操作并在表上重新添加约束

      【讨论】:

        【解决方案4】:

        您可以使用约束对 DataTable 中的数据实施限制,以保持数据的完整性。当DataSetSystem.Data.DataSet.EnforceConstraints 属性为真时,会强制执行约束。

        ADO.NET 中有两种约束:ForeignKeyConstraint 和 UniqueConstraint。默认情况下,当您通过将DataRelation 添加到DataSet 来创建两个或多个表之间的关系时,会自动创建这两个约束。但是,您可以通过在创建关系时指定 createConstraints = fals 来禁用此行为。

        【讨论】:

        • 问题是关于暂时禁用约束...感谢您的解释
        【解决方案5】:

        如果加载时数据表中有数据,可能会抛出异常。 为了安全起见,请在加载之前清除数据表,如下所示:

        MyDataTable.Clear();
        MyDataTable.Load(MyDataReader, LoadOption.OverwriteChanges);
        

        这对我有用:)

        【讨论】:

        • @Downvoter:您能否添加一条评论来解释您投反对票的原因?这可能对某人有所帮助。
        【解决方案6】:

        当您选择键列(即在 JOIN 中)并且结果表在结果表中具有多个相同值时,通常会发生此异常。 假设您有一个带有 CustID-PK 的客户表,并且您将该表与一个地址表连接起来,其中关系为 1..n。客户可以拥有多个地址。您最终会得到一个结果表,其中所有地址都重复了 CustID。 数据表加载源模式并看到 CustID 是一个 PK,因此它是唯一的,但 JOIN 命令的结果表在 CustID 列中具有该值的重复。然后异常发生。

        如果你想处理和收集错误:

                using var tbl = new DataTable();
                using var reader = cmd.ExecuteReader();
        
                tbl.BeginLoadData();
        
                try
                {
                    tbl.Load(reader);
                }
                catch (ConstraintException ex)
                {
                    var sb = new StringBuilder();
        
                    foreach (var row in tbl.GetErrors())
                    {
                        sb.AppendLine(row.RowError);
        
                        foreach (var col in row.GetColumnsInError())
                        {
                            var colError = col.ColumnName
                                           + ":" + row.GetColumnError(col);
                            sb.AppendLine(colError);
                        }
                    }
        
                    reader.Close();
                    tbl.Clear();
                    tbl.Constraints.Clear();
        
                    if (IgnoreErrors)
                        tbl.Load(cmd.ExecuteReader());
                    else
                        throw new ConstraintException(sb.ToString(), ex);
                }
                finally
                {
                    tbl.EndLoadData();
                }
        

        “IgnoreErrors”是数据层或实体加载器等中的一个属性。

        如果您想避免该错误,请将源列重命名为“AS”:

        "SELECT A.*, C.CustID AS CustIDNew FROM Addresses AS A INNER JOIN Customer AS C ON C.CustID = A.lCustID"
        

        问候

        【讨论】:

          猜你喜欢
          • 2010-11-10
          • 2017-01-02
          • 2010-10-05
          • 2016-03-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-10-13
          相关资源
          最近更新 更多