2012-06-14 3 views
0

Я пытаюсь удалить все строки в таблице, используя Castle ActiveRecord. Обычно я бы сделал это:Есть ли быстрый способ удалить все строки в таблице с помощью Castle ActiveRecord или nHibernate?

DB.ParseError.DeleteAll(); 

Однако в этой таблице около 1,9 миллиона строк. То, что выше команда будет делать это выпустить отдельный 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.

Есть ли еще официальный способ удалить таблицу, не делая 2 оператора SQL в строке?

ответ

3

Для таблицы с тем, что многие записи, вы определенно не хотите, чтобы создать объект для каждой строки, а затем удалить его - это будет длиться вечно.

Если у вас нет каких-либо правил каскадных, определенных в ваших отображениях, которые не исполняется в вашей базе данных, то проще всего использовать SQL-запрос:

ActiveRecordBase<ParseError>.Execute(
    (s, i) => s.CreateSQLQuery("DELETE FROM ParseErrors").ExecuteUpdate(), 
              null); 

Это аннулирует кэша NHibernate (поэтому он будет хорошо играть с кешем второго уровня NHibernate), но он не будет делать никаких каскадов, не определенных в db (я подозреваю, что это будет хорошо для вашего случая). Если есть какие-то каскады, которые не находятся в db, вам придется делать их вручную.

Если вы действительно хотите, чтобы он использовал сущности для удаления, используйте, по крайней мере, StatelessSessionScope, который не позволит ему добавлять все сущности в сеанс как минимум.

UPDATE:

Execute() метод является защищенным членом ActiveRecordBase<T>, поэтому называть его вне класса вы должны обернуть его в общественном статическом методе.

+0

Нет каскадных правил, поэтому это должно отлично работать! Спасибо.. –

1

Вы можете удалить все записи из таблицы с помощью nHibernate со следующим утверждением. В зависимости от каскадных правил. Возможно, сначала вам нужно очистить другую таблицу.

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

Use full link

+2

Это приведет к тому, что NHibernate загрузит все объекты и удалит их 1 на 1, что является тем, чего он пытается избежать. –

0

Здравствуйте Майк Кристенсен,

да Ther способ.Это не хороший способ (я думаю), но это лучше, чем обычный SQL:

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

Batch Update in NHibernate

Поздравь Juy Juka

1

Каждый раз, когда я имел дело с этим в мимо я сделал что-то вроде:

session.CreateSQLQuery("DELETE FROM FOO").ExecuteUpdate(); 

Да, он обходит все виды вещей, но я никогда не имел проблем с этим.

У Ayende есть post on this, который использует объемную копию, чтобы сделать это, но, похоже, не затрагивает ваши проблемы с кешированием.