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

4
我有一个查询,它会删除所有被标记为删除的行。表中有一个名为IsDeleted的列,如果它为true,则应该删除该行以及其他表中所有相关行。
如果文章行被标记为删除,则文章评论、投票也应该被删除。哪种ORM可以有效处理这个问题? 编辑 我需要用于C# .NET。

1
你使用的是哪种编程语言和框架?答案很大程度上取决于你是使用Java还是.Net还是Python等。 - John Paulett
6个回答

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倍)。异步批处理执行将进一步改善此问题。

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


1

NHibernate支持HQL(面向对象的Hibernate Query Language)更新和删除。

这里有一些例子,可以参考Fabio Maulo的博客文章Ayende Rahien的博客文章

它可能看起来像这样:

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

注意:这不是SQL。这是包含类名和属性名的HQL,并且可以翻译成(几乎)任何数据库。

1

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

如果您想定期清除IsDeleted行,则使用本机SQL在RDBMS中安排这些作业要更有效率,只要按正确顺序删除事物,以便不会破坏引用完整性。如果您不在DB级别执行引用完整性,则顺序无关紧要。

即使多年来我所有数据库设计都具有强大的引用完整性和约束条件,我从未使用过级联RI-在我的设计中从未需要过。


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)

我可以像这样做吗?userRoles.DeleteMulti('查询语句放在这里') - Luke101

0
  1. 哪些ORM支持基于“条件”的删除...我使用过的两个(Propel,Doctrine)都支持。我认为除非它们处于开发早期,否则几乎所有ORM都支持,因为这是一个相当基本的功能。但是你在用什么语言?

  2. 至于你的级联删除,最好在数据库级别上使用外键来实现。大多数关系型数据库管理系统都支持此功能。如果你使用的是不支持此功能的东西,则一些ORM也会实现此功能。但我的建议是只使用支持此功能的关系型数据库管理系统。从长远来看,这将减少头痛。


如果您想删除所有太旧的日志(> 5年),那么外键将没有什么用处。我认为这可能是类似的情况。 - James Black

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

我认为Entity Framework也应该允许这样做,但我从未使用过,你可以研究一下。

基本上,找到一个具有所需功能的ORM,然后您可以询问如何在所选的ORM中执行此查询。我认为仅为此选择ORM是有风险的,因为还有许多其他因素应该考虑进选择中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接