我有一个查询,删除所有已标记为删除的行。表中有一列名为 IsDeleted 。它是一个布尔数据类型,如果是,则假定该行与不同表中的所有相关行一起被删除。
如果文章行被标记为删除,那么文章评论,投票也可以删除。哪个ORM可以有效地处理这个问题?
修改
我需要这个用于C#.NET
答案 0 :(得分:2)
DataObjects.Net提供了一个中间解决方案:
所以这很快,虽然还不理想:
因此,在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 Maulo和this 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)
ORM的支持“标准”基于删除...我曾与之合作过的两个(Propel,Doctrine)。我认为几乎所有人都会这样做,除非他们在发展初期是非常基本的事情。但你在用什么语言工作?
就删除级联而言,最好在数据库级别使用外键实现。大多数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的简要教程。
我希望实体框架也允许它,但我从未使用它,但你可以调查它。
基本上,找到具有所需功能的ORM,然后您可以询问如何在所选ORM中执行此查询。我认为为这一特征选择ORM是有风险的,因为选择中还有许多其他因素。