如何实现递归删除?

时间:2009-12-10 09:29:20

标签: c# design-patterns sql-server-2008 recursion

我有以下情况:

客户包含项目和项目包含许可证。 好,因为归档我们不会删除任何东西,但我们使用IsDeleted代替。 其他我可以使用级联删除。

Owkay我使用存储库模式,所以我打电话给

customerRepository.Delete(customer);

但是这里开始出现问题。客户被设置为isdeleted true。但后来我想删除该客户的所有项目,每个被删除的项目也应该删除所有许可证。

我想知道是否有适当的解决方案。 但它必须具有高性能。

请注意,这是实际问题的简单版本。客户还有与许可证相关联的网站,但我只是想为您解决问题。

我在使用sql server 2008作为数据库的C#环境中工作。

编辑:我正在使用enterprice库连接数据库

4 个答案:

答案 0 :(得分:2)

一种选择是在带有触发器的数据库中执行此操作。我想另一种选择是使用Cascade更新,但这可能不适合你的域名如何运作。

我个人可能只是咬紧牙关并编写C#代码来为我设置IsDeleted类型字段(如果只有一个应用程序访问数据库)。

答案 1 :(得分:1)

我建议只编写一个存储过程(或一组存储过程)来封装这个逻辑,它看起来像这样:

update Customer set isDeleted = 1
where  CustomerId = @CustomerId

/* Say the Address table has a foreign key to customer */
update Address set isDeleted = 1
where  CustomerId = @CustomerId

/* 
   To delete related records that also have child data,
   write and call other procedures to handle the details 
*/
exec DeleteProjectByCustomer(@CustomerId)

/* ... etc ... */

然后在事务中从customerRepository.Delete调用此过程。

答案 2 :(得分:0)

这完全取决于你的DAL。例如,NHibernate映射可以设置为级联删除所有这些关联的对象而无需额外的代码。我确信EF有类似的东西。你是如何连接数据库的?

如果您的对象没有持久化,那么一旦没有对它们的引用,.NET GC将扫除所有项目对象。我从你的问题中推测你是在谈论从数据库中删除它们吗?

答案 3 :(得分:0)

如果您的关系是固定的(即许可证始终与项目相关,而项目与客户相关),您可以完全不进行级联更新。既然您已经在处理查询中的软删除的痛苦,那么您可能会添加检查层次结构的痛苦:

SELECT [...] FROM License l
JOIN Project p ON l.ProjectID = p.ID
JOIN Customer c on p.CustomerID = c.ID
WHERE l.IsDeleted <> 1 AND p.IsDeleted <> 1 AND c.IsDeleted <> 1

只有在子表上没有连接到祖先表的查询时,才会增加性能负担。

它具有级联方法的额外优点:它可以让您取消删除项目而不会自动取消删除他们的孩子。如果我删除项目的许可证之一,然后删除项目,然后取消删除项目,级联方法将失去我删除第一个许可证的事实。这种方法不会。

在对象模型中,您可以像这样实现它:

private bool _IsDeleted;
public bool IsDeleted
{
   get
   {
      return _IsDeleted || (Parent == null ) ? false : Parent.IsDeleted;
   }
   set
   {
      _IsDeleted = value;
   }
}

...虽然您必须小心地将私有_IsDeleted值存储在数据库中,而不是IsDeleted的值。