C# 使用Castle ActiveRecord或nHibernate有没有快速删除表中所有行的方法?
我正在尝试使用Castle ActiveRecord删除表中的所有行。通常,我会这样做: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
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加载所有实体并逐个删除它们,这是他试图避免的