哪个ORM支持多行更新和删除

时间:2009-12-08 14:53:36

标签: c# sql orm

我有一个查询,删除所有已标记为删除的行。表中有一列名为 IsDeleted 。它是一个布尔数据类型,如果是,则假定该行与不同表中的所有相关行一起被删除。

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

修改

我需要这个用于C#.NET

6 个答案:

答案 0 :(得分: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

显然,这种方法比批量服务器端更新慢。根据我们的估计,在最坏的情况下([bigint Id,bigint Value]表,聚集主索引,没有其他索引),我们现在拥有的速度比真正的服务器端删除慢5倍;对于现实案例(更多列,更多索引,更多数据),它必须立即带来可比较的性能(即慢2-3倍)。异步批处理执行将进一步改善这一点。

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

答案 1 :(得分:1)

NHibernate支持HQL(面向对象的 H ibernate Q uery L 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,它转换为(几乎)任何数据库。

答案 2 :(得分:1)

通常,如果您已经在使用IsDeleted标志范例,那么这些项通常会被应用程序对象模型忽略,这是高效可靠的,因为不需要检查参照完整性(没有级联),也没有数据是永久毁灭。

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

多年来,即使我的所有数据库设计都具有强大的参照完整性和约束,我也从未使用过级联RI - 在我的设计中它从未被人们所希望。

答案 3 :(得分:0)

  1. ORM的支持“标准”基于删除...我曾与之合作过的两个(Propel,Doctrine)。我认为几乎所有人都会这样做,除非他们在发展初期是非常基本的事情。但你在用什么语言工作?

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

答案 4 :(得分:0)

我正在使用LLBLgen,它可以进行级联删除。你可能想尝试一下,这非常好。 例。从rolenames []

中的所有角色中删除username []中的所有用户
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)

答案 5 :(得分: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是有风险的,因为选择中还有许多其他因素。