我可以从 InvalidConstraintException 中检索受影响的约束吗?
Can I retrieve the impacted constraint(s) from a InvalidConstraintException?
两天前,。那个问题已经回答了,但是现在我想概括一下我的程序:
目前我有:
try
{
dt_MainTable1.Rows[0].Delete();
}
catch (Exception ex)
{
if (MessageBox.Show("In order to avoid data corruption, not only " +
" the required tupple will be deleted, " +
"but also the ones in other tables, " +
"referring to that tupple. " +
"Is that what you want?",
"Warning",
MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{
(ForeignKeyConstraint)(dt_SubTable1.Constraints[0]).DeleteRule
= Rule.Cascade;
dt_MainTable1.Rows[0].Delete();
(ForeignKeyConstraint)(dt_SubTable1.Constraints[0]).DeleteRule
= Rule.None;
}
}
... 这就是我想要的:我尝试做一些事情(比如修改或删除),但我陷入 System.Data.InvalidConstraintException
,基于 Constraint
.然后我提出一个问题,并根据答案将受影响的 Constraint
的 Deletion Rule
或 Modification Rule
转换为 None
或 Cascade
。大问题:我可以从生成的 System.Data.InvalidConstraintException
中检索受影响的 Constraint
吗? (我一直在调试和检查System.Data.InvalidConstraintException
的属性,但我没有找到任何东西),只是为了展示我想要的(见ex.FindRelevantConstraints()
方法):
try
{
LaunchDeleteAction(...);
}
catch (Exception ex)
{
if (MessageBox.Show("In order to avoid data corruption, not only " +
" the required tupple will be deleted, " +
"but also the ones in other tables, " +
"referring to that tupple. " +
"Is that what you want?",
"Warning",
MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{
for each (ForeignKeyConstraint C in ex.FindRelevantConstraints() <===
C.DeleteRule = Rule.Cascade;
LaunchDeleteAction(...);
for each (ForeignKeyConstraint C in ex.FindRelevantConstraints() <===
C.DeleteRule = Rule.None;
}
}
进一步调查后编辑
与此同时,我发现 Exception
、ex
包含相应 Constraint
的名称,您可以在下面的手表 window 摘录中看到:
ex.Message : Cannot delete this row because constraints are enforced on relation Constraint1, and deleting this row will strand child rows.
我的意思是,解析 Exception
的消息不可能是为了获得对我正在寻找的 Constraint
对象的引用?
绝望编辑
与此同时,我决定为我正在创建的 Constraint
对象指定特殊的名称,就像您在此处看到的那样:
dt_SubTable1.Constraints.Add(
new ForeignKeyConstraint("|FKC|MainTable.SubId|SubTable.Id|",
dt_SubTable.Columns["Id"],
dt_MainTable.Columns["SubId"])
{ DeleteRule = Rule.None,
UpdateRule = Rule.None });
如您所见,我可以使用管道字符分隔 table 名称,使用点来查找列名称,但这确实是一个绝望的想法:-)
作为一般规则,最好测试是否存在会导致异常的事物,而不是捕获它。
同样在 catch 块中处理用户交互并不理想,更改数据完整性约束以执行操作似乎是错误的处理方式。
更好的方法可能是:
- 测试其他 tables
中是否存在任何相关数据
- 如果找到:向用户显示消息
- 如果用户点击继续:先删除相关数据,最后删除父记录
如果关系像示例中的主要和子 table 一样简单,您可以尝试类似
if (dt_SubTable1.AsEnumerable.Any(r => s => r.Field("ForeignIdField") == MainId))
如果您有几个 DataTable
个实例,您可以遍历它们检查代码中的 Constraints
属性。
foreach (var constraint in dt_Sub1.Contstraints)
{
if (constraint is ForeignKeyConstraint && constraint.RelatedTable.TableName = dt_Main.TableName)
// check for matching data
}
如果您正在尝试更通用的方法 This question 有几种方法展示了如何找到给定 table 的外键。您可以创建一个方法 FindRelevantConstraints(string tableName)
包装系统存储过程 sp_fkeys
,它将 return table 名称和字段名称。
这将允许您使用 id 值
为依赖于您的主要 table 的任何和所有子 table 创建查询
直接回答标题中的问题:
Can I retrieve the impacted constraint(s) from a InvalidConstraintException?
不,很遗憾,你不能。
根据参考来源,InvalidConstraintException
除了消息文本和(如果适用)内部异常之外不存储任何有用的信息。
一些额外的阅读表明 the System.Data
methods pass all relevant information (e.g. the constraint name) to the ExceptionBuilder
methods,但是,唉,这个信息只用于创建异常消息然后被丢弃。
两天前,
目前我有:
try
{
dt_MainTable1.Rows[0].Delete();
}
catch (Exception ex)
{
if (MessageBox.Show("In order to avoid data corruption, not only " +
" the required tupple will be deleted, " +
"but also the ones in other tables, " +
"referring to that tupple. " +
"Is that what you want?",
"Warning",
MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{
(ForeignKeyConstraint)(dt_SubTable1.Constraints[0]).DeleteRule
= Rule.Cascade;
dt_MainTable1.Rows[0].Delete();
(ForeignKeyConstraint)(dt_SubTable1.Constraints[0]).DeleteRule
= Rule.None;
}
}
... 这就是我想要的:我尝试做一些事情(比如修改或删除),但我陷入 System.Data.InvalidConstraintException
,基于 Constraint
.然后我提出一个问题,并根据答案将受影响的 Constraint
的 Deletion Rule
或 Modification Rule
转换为 None
或 Cascade
。大问题:我可以从生成的 System.Data.InvalidConstraintException
中检索受影响的 Constraint
吗? (我一直在调试和检查System.Data.InvalidConstraintException
的属性,但我没有找到任何东西),只是为了展示我想要的(见ex.FindRelevantConstraints()
方法):
try
{
LaunchDeleteAction(...);
}
catch (Exception ex)
{
if (MessageBox.Show("In order to avoid data corruption, not only " +
" the required tupple will be deleted, " +
"but also the ones in other tables, " +
"referring to that tupple. " +
"Is that what you want?",
"Warning",
MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{
for each (ForeignKeyConstraint C in ex.FindRelevantConstraints() <===
C.DeleteRule = Rule.Cascade;
LaunchDeleteAction(...);
for each (ForeignKeyConstraint C in ex.FindRelevantConstraints() <===
C.DeleteRule = Rule.None;
}
}
进一步调查后编辑
与此同时,我发现 Exception
、ex
包含相应 Constraint
的名称,您可以在下面的手表 window 摘录中看到:
ex.Message : Cannot delete this row because constraints are enforced on relation Constraint1, and deleting this row will strand child rows.
我的意思是,解析 Exception
的消息不可能是为了获得对我正在寻找的 Constraint
对象的引用?
绝望编辑
与此同时,我决定为我正在创建的 Constraint
对象指定特殊的名称,就像您在此处看到的那样:
dt_SubTable1.Constraints.Add(
new ForeignKeyConstraint("|FKC|MainTable.SubId|SubTable.Id|",
dt_SubTable.Columns["Id"],
dt_MainTable.Columns["SubId"])
{ DeleteRule = Rule.None,
UpdateRule = Rule.None });
如您所见,我可以使用管道字符分隔 table 名称,使用点来查找列名称,但这确实是一个绝望的想法:-)
作为一般规则,最好测试是否存在会导致异常的事物,而不是捕获它。
同样在 catch 块中处理用户交互并不理想,更改数据完整性约束以执行操作似乎是错误的处理方式。
更好的方法可能是:
- 测试其他 tables 中是否存在任何相关数据
- 如果找到:向用户显示消息
- 如果用户点击继续:先删除相关数据,最后删除父记录
如果关系像示例中的主要和子 table 一样简单,您可以尝试类似
if (dt_SubTable1.AsEnumerable.Any(r => s => r.Field("ForeignIdField") == MainId))
如果您有几个 DataTable
个实例,您可以遍历它们检查代码中的 Constraints
属性。
foreach (var constraint in dt_Sub1.Contstraints)
{
if (constraint is ForeignKeyConstraint && constraint.RelatedTable.TableName = dt_Main.TableName)
// check for matching data
}
如果您正在尝试更通用的方法 This question 有几种方法展示了如何找到给定 table 的外键。您可以创建一个方法 FindRelevantConstraints(string tableName)
包装系统存储过程 sp_fkeys
,它将 return table 名称和字段名称。
这将允许您使用 id 值
为依赖于您的主要 table 的任何和所有子 table 创建查询直接回答标题中的问题:
Can I retrieve the impacted constraint(s) from a InvalidConstraintException?
不,很遗憾,你不能。
根据参考来源,InvalidConstraintException
除了消息文本和(如果适用)内部异常之外不存储任何有用的信息。
一些额外的阅读表明 the System.Data
methods pass all relevant information (e.g. the constraint name) to the ExceptionBuilder
methods,但是,唉,这个信息只用于创建异常消息然后被丢弃。