5

我希望能够检查从SQL Server 2008中的表中删除行是否会由于外键违例而未尝试删除而失败。检查是否安全删除一行

基本上,我不想向用户显示一个删除按钮,如果他们不能删除它,因为密钥在其他地方使用。

我在应用程序的许多地方都需要这样,因此不需要手动编写检查以查看是否可以安全地删除该行。有关实现此目标的最佳方法的任何建议?

我正在使用实体框架访问数据。

回答

2

没有快速简单的方法来检查这一点。你可以使用information_schema来构建一些动态的东西,但它无疑会变得丑陋而不是很快。

绝对的最佳选择是用于验证每个位置的自定义代码的几行代码。

另一个选择是启动一个事务,尝试删除。如果失败,那么你知道。如果成功,则回滚事务,并且您知道删除是可能的。这仍然是丑陋的,并且以一种有点破碎的方式使用交易,但它会起作用。尽管如此,请确保级联删除不在桌面上。

1

我在之前的应用程序中做过这种事情。我创建了一个名为TryDelete()的函数。在该方法中,我试图删除所需的行。如果我得到FK异常,我就会抓到它并返回false。在任何一种情况下,true或false,我都将delete封装在一个事务中,然后将其回滚。

2

查询时,对子表执行LEFT JOIN。使用CanDelete计算值来决定是否显示按钮。如果您每个父行有多于1个子行,COUNT此处将删除重复项。

SELECT 
    Col1, Col2, Col3, ..., 
    CASE C.Existence WHEN 0 THEN 1 ELSE 0 END AS CanDelete 
FROM 
    ParentTable P 
    LEFT JOIN 
    (
    SELECT COUNT(*) AS Existence, FKColumn 
    FROM Childtable GROUP BY FKColumn 
    ) C ON P.FKColumn = C.FKColumn 
WHERE 
    P.Col = ... 

另一种方式可能是

SIGN(C.Existence) AS HasChildRows 
+0

好主意!但是,他正在使用EntityFramework将数据加载到对象中... – veljkoz 2010-11-23 14:16:35

1

你可以在局部类的实体是否存在被引用的对象,将检查方法的补充。

例如,假设您有Entity1,其中包含Entity2的集合。基本上,每一个实体的部分类,你会写一个属性IsReferenced会:

  • 对于ENTITY1返回true,如果ENTITY1在ENTITY2
  • 任何项目ENTITY2返回TURE如果有到ENTITY1
  • 参考

正如你猜测,你需要确保你始终在参考值的获取,或者,如果你的工作连接上下文,你可以使用.Load()IsReferenced检查之前获取实体。这是一个开销,它只取决于你是否愿意为它付费。

然后,您可以根据需要显示/隐藏“删除”按钮,以避免每次重复检查。

0

我想你在这里有两个可能的选择。由于您不能保证所有关系都将映射到您的OM中,因此您必须在数据库中检查它。

您可以尝试回滚之后一个事务中的实际delting,但如果你有contraint配置了级联删除,这也将工作...

另一种方式将提取的所有约束上sysobjects表,并验证每个表都没有记录。但是这需要一些动态的SQL,这也会变得相当混乱。

0

如果您处于数据库级别,我会加入冲突可能存在的所有表格。

任何返回的记录都不能被删除,这意味着剩下的设置可以。

0

假设数据库被多个用户使用(绝大多数用户都使用该数据库) - 在“检查”删除是可能的,并且用户可能决定删除该行之间将存在一个机会窗口,在此期间其他人可能会执行一些否定测试结果的活动。

这意味着您可能会显示“删除”按钮,但在您尝试删除时,将不再可能。此外,您可能不会显示删除按钮,但在用户决定删除该行(但无法找到该按钮)时,应该允许它们。

没有办法避免这些种族。我只是让人们尝试删除它们,但是要准备好处理由于外键导致的失败。

相关问题