如何更新跨多行的唯一约束列中的数据而不违反约束条件?

问题描述:

我有一个具有唯一约束的列的表。用户将以绑定到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"); 

一个更优雅的解决方案可以从代码做到这一点而无需访问数据库,但会假设你的过程是当时唯一一个更新。