C# 使用Castle ActiveRecord或nHibernate有没有快速删除表中所有行的方法?

C# 使用Castle ActiveRecord或nHibernate有没有快速删除表中所有行的方法?,c#,.net,nhibernate,castle-activerecord,C#,.net,Nhibernate,Castle Activerecord,我正在尝试使用Castle ActiveRecord删除表中的所有行。通常,我会这样做: DB.ParseError.DeleteAll(); 然而,这个表中碰巧有大约190万行。上面的命令将为表中的每一行发出一个单独的SELECT和DELETE,如下所示: SELECT page0_.Id as Id29_0_, ... FROM Indexer.Pages page0_ WHERE page0_.Id=:p0;:p0 = b03665aa-37d0-4a2d-a04c-c232ebd94d

我正在尝试使用Castle ActiveRecord删除表中的所有行。通常,我会这样做:

DB.ParseError.DeleteAll();
然而,这个表中碰巧有大约190万行。上面的命令将为表中的每一行发出一个单独的
SELECT
DELETE
,如下所示:

SELECT page0_.Id as Id29_0_, ... FROM Indexer.Pages page0_ WHERE page0_.Id=:p0;:p0 = b03665aa-37d0-4a2d-a04c-c232ebd94dbc [Type: Guid (0)]
SELECT page0_.Id as Id29_0_, ... FROM Indexer.Pages page0_ WHERE page0_.Id=:p0;:p0 = 11cb69e3-1c6a-4ac1-908b-084dfe859639 [Type: Guid (0)]
--- 1.9 million more of these
DELETE FROM Indexer.ParseErrors WHERE Id = :p0;:p0 = b03665aa-37d0-4a2d-a04c-c232ebd94dbc [Type: Guid (0)]
DELETE FROM Indexer.ParseErrors WHERE Id = :p0;:p0 = 11cb69e3-1c6a-4ac1-908b-084dfe859639 [Type: Guid (0)]
--- 1.9 million more of these
这需要。。。我不知道需要多长时间,因为我没有耐心让它真正结束

我想要它做的是发出一条SQL语句;这个:

DELETE FROM Indexer.ParseErrors;
以下是我迄今为止所尝试的:

ISessionFactoryHolder holder = ActiveRecordMediator.GetSessionFactoryHolder();
ISession session = holder.CreateSession(typeof(DB.ParseError));
IDbCommand cmd = session.Connection.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "DELETE FROM Indexer.ParseErrors;";
cmd.CommandTimeout = 600;
cmd.ExecuteNonQuery();
holder.ReleaseSession(session);
这似乎是可行的,但对我来说似乎是一种攻击,因为它完全避免了模型和ActiveRecord框架。另外,这可能不适合NHibernate的任何缓存


是否有一种更正式的方法来删除一个表,而不必每行执行两条SQL语句?

您可以使用以下语句删除nHibernate表中的所有记录。 取决于级联规则。您可能需要先清理另一张桌子

session.Delete("from Indexer.ParseErrors p");

您可以使用以下语句使用nHibernate从表中删除所有记录。 取决于级联规则。您可能需要先清理另一张桌子

session.Delete("from Indexer.ParseErrors p");

对于一个包含那么多记录的表,您肯定不希望它为每一行创建一个实体,然后将其删除—这将花费永远的时间

如果在映射中没有定义任何级联规则,而这些规则在数据库中没有强制执行,那么最简单的方法是使用SQL查询:

ActiveRecordBase<ParseError>.Execute(
    (s, i) => s.CreateSQLQuery("DELETE FROM ParseErrors").ExecuteUpdate(),
                                           null);
ActiveRecordBase.Execute(
(s,i)=>s.CreateSQLQuery(“从ParseErrors中删除”).ExecuteUpdate(),
无效);
这将使NHibernate缓存失效(因此它将很好地与NHibernate二级缓存配合使用),但它不会执行db中未定义的任何级联(我怀疑这对您的情况来说是合适的)。如果有任何级联不在db中,那么您必须手动执行它们

如果您真的希望它使用要删除的实体,那么至少要使用无状态会话范围,这至少会阻止它将所有实体添加到会话中

更新:


Execute()
方法是
ActiveRecordBase
的受保护成员,因此要从类外调用它,必须将其包装在公共静态方法中。

对于一个包含这么多记录的表,您肯定不希望它为每一行创建一个实体,然后删除它-这将花费很长时间

如果在映射中没有定义任何级联规则,而这些规则在数据库中没有强制执行,那么最简单的方法是使用SQL查询:

ActiveRecordBase<ParseError>.Execute(
    (s, i) => s.CreateSQLQuery("DELETE FROM ParseErrors").ExecuteUpdate(),
                                           null);
ActiveRecordBase.Execute(
(s,i)=>s.CreateSQLQuery(“从ParseErrors中删除”).ExecuteUpdate(),
无效);
这将使NHibernate缓存失效(因此它将很好地与NHibernate二级缓存配合使用),但它不会执行db中未定义的任何级联(我怀疑这对您的情况来说是合适的)。如果有任何级联不在db中,那么您必须手动执行它们

如果您真的希望它使用要删除的实体,那么至少要使用无状态会话范围,这至少会阻止它将所有实体添加到会话中

更新:


Execute()
方法是
ActiveRecordBase
的受保护成员,因此要从类外调用它,必须将其包装在公共静态方法中。

您好Mike Christensen

是的,有办法。这不是一个好方法(我认为),但它比普通SQL更好:

session.CreateQuery(@"UPDATE " + typeof(?).FullName + " SET Property = :value")
       .SetParameter("value",valueVariable)
       .ExecuteUpdate();

问候
Juy Juka

你好,迈克·克里斯滕森

是的,有办法。这不是一个好方法(我认为),但它比普通SQL更好:

session.CreateQuery(@"UPDATE " + typeof(?).FullName + " SET Property = :value")
       .SetParameter("value",valueVariable)
       .ExecuteUpdate();

问候
Juy Juka

过去每次我处理这个问题时,我都会做一些类似的事情:

session.CreateSQLQuery("DELETE FROM FOO").ExecuteUpdate();
是的,它绕过了所有的东西,但我从来没有遇到过这样的问题


Ayende有一个应用程序,它使用bulkcopy来完成这项工作,但似乎没有解决您对缓存的担忧

过去每次我处理这个问题时,我都会这样做:

session.CreateSQLQuery("DELETE FROM FOO").ExecuteUpdate();
是的,它绕过了所有的东西,但我从来没有遇到过这样的问题


Ayende有一个应用程序,它使用bulkcopy来完成这项工作,但似乎没有解决您对缓存的担忧

这将导致NHibernate加载所有实体并逐个删除它们,这是他试图避免的,这将导致NHibernate加载所有实体并逐个删除它们,这是他试图避免的