2009-12-08 52 views
4

我有一个查询删除所有标记为删除的行。表格中有一列名为IsDeleted。它是一个布尔数据类型,如果它是真的,假设该行与不同表中的所有相关行一起被删除。哪个ORM支持多行更新和删除

如果文章行被标记为删除,那么文章评论,投票也被删除。哪个ORM可以有效地处理这个问题?

编辑

我需要这个C#.NET

+1

您使用的是什么语言和框架?答案很大程度上取决于你是否使用Java vs .Net vs Python等。 – 2009-12-08 14:58:39

+0

这将用于c# – Luke101 2009-12-08 15:13:37

回答

2

DataObjects.Net提供了一个中间的解决方案:

  • 目前,它不能执行服务器端通过缺失查询中所选择的实体。这将在一天内实施,但现在还有另一种解决方案。
  • 另一方面,就是支持所谓的泛化配料:查询它发送一次最多可以批量发送25个项目,这是可能的。 “可能”意味着“查询结果现在不需要”。这对于创建,更新和删除几乎总是正确的。由于这样的查询总是会导致单个(或者很少,如果有继承)寻求操作,所以它们非常便宜。如果它们是以大容量形式发送的,SQL Server可以缓存整个大块的计划,而不仅仅是针对单个查询。

所以这是非常快的,虽然目前还没有理想:

  • 现在DO4不使用IN(...)来优化这种缺失。
  • 到目前为止,它不支持异步批处理执行。当这样做完成后(我希望这将在一个月左右完成),它在CUD(一个CRUD的子集)操作上的速度将与SqlBulkCopy几乎相同(约为现在的1.5倍... 2倍) 。

所以,如果与DO批量删除如下所示:

var customersToRemove = 
    from customer in Query<Customer>.All 
    where customer.IsDeleted 
    select customer; 

foreach (customer in customersToRemove) 
    customer.Remove(); // This will be automatically batched 

我能说出这种方法的好处:任何物体就能上删除反应;会话事件订阅者也会收到关于每个删除的通知。因此,与删除相关的任何常见逻辑将按预期工作。这是不可能的,如果这样的操作在服务器上执行。

代码软删除必须像:

var customersToRemove = 
    from customer in Query<Customer>.All 
    where ... 
    select customer; 

foreach (customer in customersToRemove) 
    customer.IsRemoved = true; // This will be automatically batched 

很显然,这样的做法是慢于批量服务器端更新。根据我们的估计,现在我们现在的速度比最差情况下的真正服务器端删除速度慢5倍左右([bigint Id,bigint Value]表,聚集主索引,没有其他索引);在现实生活中(更多的专栏,更多的索引,更多的数据),它现在必须带来类似的表现(即慢2-3倍)。异步批处理将进一步改进。

顺便说一下,我们与ORMBattle.NET的各种ORM框架的实体共享了散装CUD操作的测试。请注意,那里的测试不使用批量服务器端更新(实际上,这样的测试将是对数据库性能而不是ORM的测试);相反,他们测试ORM是否能够优化这一点。无论如何,如果您正在评估多个ORM工具,那么提供的信息+ test code可能会有帮助。

0
  1. 了基于删除ORM的支持 “标准” ......无论是那些我曾经使用过的(行走,学说) 。我认为几乎所有的人都会这样做,除非他们在开发早期就已经成为其基本的东西。但是你在用什么语言工作?

  2. 就您的删除级联而言,这最好在数据库级别用外键实现。大多数RDBMS都支持这一点。如果你使用的东西没有一些ORM的实现,以及如果支持不可用。但我的建议是只使用支持它的RDBMS。从长远来看,这将不那么令人头疼。

+0

如果你想删除所有太旧(大于5岁)的日志,那么FK将是最小的使用。这可能是一个类似的情况,我预计。 – 2009-12-08 15:21:17

1

NHibernate的支持HQL(面向对象ħ ibernate Q uery 大号 anguage)更新和删除。

this Blog Post by Fabio Maulothis Blog Post by Ayende Rahien中有一些示例。

它可能会是这样的:

using (var session = OpenSession()) 
using (var tx = s.BeginTransaction()) 
{ 
    session 
    .CreateQuery("delete from Whatever where IsDelete = true") 
    .ExecuteUpdate(); 
    tx.Commit(); 
} 

注:这不是SQL。这是包含类名称和属性名称的HQL,它转化为(几乎)任何数据库。

0

我使用LLBLgen,它可以级联删除。你可能想尝试一下,这很好。 示例。删除用户名[]所有用户的所有角色中的角色名[]

string[] usernames; 
string[] rolenames; 

UserRoleCollection userRoles = new UserRoleCollection(); 
PredicateExpression filter = new PredicateExpression(); 
filter.Add(new FieldCompareRangePredicate(UserFields.logincode, usernames)); 
filter.AddWithAnd(new FieldCompareRangePredicate(RoleFields.Name, rolenames)); 
userRoles.DeleteMulti(filter) 
+0

我可以使用LLBLgen执行多行更新和删除吗? – Luke101 2009-12-08 15:15:37

+0

我可以这样做吗? userRoles.DeleteMulti('query goes here') – Luke101 2009-12-08 17:15:38

1

通常情况下,如果你已经使用请将isDeleted标志的范例,该项目通常由应用对象模型忽略了,这是有效的,可靠的因为不需要检查参照完整性(无级联),也不会永久销毁数据。

如果您希望定期清除IsDeleted行,那么使用本机SQL将这些行作为批处理作业安排在RDBMS中效率更高,只要您按照正确的顺序删除内容,以免参照完整性受到影响。如果您不在数据库级强制执行参照完整性,那么订单无关紧要。

即使在多年来我的所有数据库设计中都有很强的参照完整性和约束条件,但我从来没有使用级联RI - 这在我的设计中从未令人满意。

0

大多数ORM将允许您提供SQL提示或在其框架中执行SQL。

例如,您可以在DLINQ中使用ExecuteQuery方法来做你想做的事。这里是一个关于使用DLINQ自定义sql的简要教程。

http://weblogs.asp.net/scottgu/archive/2007/08/27/linq-to-sql-part-8-executing-custom-sql-expressions.aspx

我会想到的是,实体框架也将允许它,但我从来没有使用过它,但你可以看看它。

基本上,找到一个具有所需功能的ORM,然后可以询问如何在选定的ORM中执行此查询。我认为为这个功能选择一个ORM是有风险的,因为还有很多其他因素需要选择。