如何更新跨多行的唯一约束列中的数据而不违反约束条件?
问题描述:
我有一个具有唯一约束的列的表。用户将以绑定到DataGrid的DataTable的形式编辑此表中的数据。完成修改数据后,保存功能必须将其更改应用到数据库。出于应用程序体系结构的原因,对数据库的每次更改都必须一次一行地执行创建,更新或删除操作。我可以验证DataTable以确保最终结果不违反约束,但似乎不可能验证它永远不会被违反。即使我不允许DataGrid内部存在重复值,用户可以在做出违反约束的修改时放置占位符值,并且DataTable类似乎只存储每行的原始版本和最终版本,而不是中间版本。如何更新跨多行的唯一约束列中的数据而不违反约束条件?
如何在对数据进行这些更改时避免任何唯一的约束违规?
答
最简单的办法是更新所有限制值的一个SQL语句:
UPDATE [Foo] Set [SomeUniqueValue] = CASE [ID] WHEN 1 THEN 'A' WHEN 2 THEN 'B' WHEN 3 THEN 'C' END WHERE [ID] IN (1,2,3)
这不会违反独特如果你身边交换价值,只要唯一性是由保存声明完成的时间。
如果你必须一次做一行,你可能不得不暴力地遍历你的更新列表,在失败时捕获错误,并在一个循环中不断重试那些错误的,直到所有更新都是完成或没有更多的更新,可以做出:
bool didSomething;
List<Row> rowsThatNeedToTryAgain = new List<Row>();
do {
didSomething = false;
rowsThatNeedToTryAgain.Clear();
foreach (Row row in rowsToUpdate) {
try {
UpdateTheRowInTheDatabase(row);
didSomething = true;
} catch {
rowsThatNeedToTryAgain.Add(row);
}
}
rowsToUpdate.Clear();
rowsToUpdate.AddRange(rowsThatNeedToTryAgain);
} while (didSomething && rowsThatNeedToTryAgain.Count > 0);
if (rowsThatNeedToTryAgain.Count > 0)
throw new Exception("sorry, couldn't do 'em all");
一个更优雅的解决方案可以从代码做到这一点而无需访问数据库,但会假设你的过程是当时唯一一个更新。