在一个数据集中,有一个EnforceConstraints属性,指示是否启用约束条件。虽然DataTable也可以具有约束条件,但我无法禁用DataTable的约束条件。
我的情况是,我有一个DataTable,在其中使用一个列上的UniqueConstraint进行内存操作。有时我想临时禁用唯一约束条件。我该怎么做?我想到的唯一方法是删除并重新添加约束条件。有更好的方法吗?
在一个数据集中,有一个EnforceConstraints属性,指示是否启用约束条件。虽然DataTable也可以具有约束条件,但我无法禁用DataTable的约束条件。
我的情况是,我有一个DataTable,在其中使用一个列上的UniqueConstraint进行内存操作。有时我想临时禁用唯一约束条件。我该怎么做?我想到的唯一方法是删除并重新添加约束条件。有更好的方法吗?
我的解决方案是这样的
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;
}
DataTable
没有公共的EnforceConstraints
属性。我建议采用以下方法之一来禁用约束:
DataTable.BeginLoadData()
方法,再使用DataTable.EndLoadData()
方法重新启用约束。DataTable
添加到一个(虚拟的)DataSet
中,并将属性DataSet.EnforceConstraints
设置为false。注意:禁用检查约束也会禁用检查与DataColumn.AllowDBNull
和DataColumn.MaxLength
相关的值。
您可以使用约束来强制限制 DataTable 中的数据,以维护数据的完整性。当 DataSet 的 System.Data.DataSet.EnforceConstraints 属性为 true 时,会执行约束。
ADO.NET 中有两种约束:ForeignKeyConstraint 和 UniqueConstraint。默认情况下,当通过向 DataSet 添加 DataRelation 来创建两个或多个表之间的关系时,这两种约束都会自动创建。但是,您可以在创建关系时指定 createConstraints = false 来禁用此行为。
这种异常通常发生在选择关键列(例如在JOIN操作中)时,结果表中有多个相同的值。比如你有一个客户表,其中CustID是主键,然后你将其与一个地址表进行连接,关系为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();
}
"SELECT A.*, C.CustID AS CustIDNew FROM Addresses AS A INNER JOIN Customer AS C ON C.CustID = A.lCustID"
敬礼
如果在加载datatable时存在数据,则可能会引发异常。为了安全起见,在加载之前请清除您的datatable,如下所示:
MyDataTable.Clear();
MyDataTable.Load(MyDataReader, LoadOption.OverwriteChanges);
这对我有用 :)