EnforceConstraint on Datatable
On a dataset is a EnforceConstraints property indicating whether the constraints should b开发者_如何学编程e enabled. Althought a datatable also can have constraints i cannot disable the constraints for a datatable.
My case is that I have datatable which i use in memory with a uniqueconstraint on one of the columns. Sometimes i want to temporarily disable the unique constraint. How can I do this? The only thing I came up with is removing and re-adding the constraint. Is there a better way?
My solution is this
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;
}
There is no public EnforceConstraints
property on DataTable
. I propose one of the following methods to disable constraints:
- To temporarily disable constraints use method
DataTable.BeginLoadData()
and thenDataTable.EndLoadData()
to reenable them again. - Add that DataTable to a (dummy) DataSet and set property
DataSet.EnforceConstraints
to false.
Note: Disabling checking constraints also disables checking values regarding DataColumn.AllowDBNull
and DataColumn.MaxLength
.
Basically what i did is loop through the contrains and remove them. Do the action and re-add the constraints on the table
You can use constraints to enforce restrictions on the data in a DataTable, in order to maintain the integrity of the data. Constraints are enforced when the System.Data.DataSet.EnforceConstraints
property of the DataSet
is true.
There are two kinds of constraints in ADO.NET: the ForeignKeyConstraint
and the UniqueConstraint. By default, both constraints are created automatically when you create a relationship between two or more tables by adding a DataRelation
to the DataSet
. However, you can disable this behavior by specifying createConstraints = fals
when creating the relation.
This exceptions mostly occurs when you select key columns i.e. in a JOIN and the resulting table has more than one of the same value in the resulting table. Imagine you have a customer table with a CustID-PK and you join this table with an address table where the relation is 1..n. The customer can have more than one address. You end up with a resulting table where CustID is repeated for all adresses. The datatable loads the source schema and sees CustID is a PK, so it's unique, but the resulting table from the JOIN-command has a repetition of that value in the CustID-column. Then the exception occurs.
If you want handle and collect the error:
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" is a property in your data layer or entity loader etc..
If you wanna avoid the error, rename the source column with "AS":
"SELECT A.*, C.CustID AS CustIDNew FROM Addresses AS A INNER JOIN Customer AS C ON C.CustID = A.lCustID"
Regards
If there is data in the datatable when you load it, an exception may be thrown. To play safe, clear your datatable before loading it like this:
MyDataTable.Clear();
MyDataTable.Load(MyDataReader, LoadOption.OverwriteChanges);
This worked for me :)
精彩评论