diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExperimentBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExperimentBO.java
index 98fd39655fc6f869898728644671d5ae8d1dbb28..d9a24e873417efa9f8ba29429efee9d4c7870c1c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExperimentBO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExperimentBO.java
@@ -207,7 +207,7 @@ public final class ExperimentBO extends AbstractBusinessObject implements IExper
                 + "') not found in experiment '" + experiment.getIdentifier() + "'.");
     }
 
-    public void deleteByTechIds(List<TechId> experimentIds, String reason)
+    public void deleteByTechIdsOld(List<TechId> experimentIds, String reason)
             throws UserFailureException
     {
         for (TechId experimentId : experimentIds)
@@ -215,7 +215,7 @@ public final class ExperimentBO extends AbstractBusinessObject implements IExper
             loadDataByTechId(experimentId);
             try
             {
-                deleteZombieDatasetPlaceholders();
+                deleteZombieDatasetPlaceholders(); // FIXME do this on deletion
                 getExperimentDAO().delete(experiment);
                 getEventDAO().persist(
                         createDeletionEvent(experiment, session.tryGetPerson(), reason));
@@ -225,6 +225,21 @@ public final class ExperimentBO extends AbstractBusinessObject implements IExper
                         EntityKind.EXPERIMENT);
             }
         }
+
+    }
+
+    public void deleteByTechIds(List<TechId> experimentIds, String reason)
+            throws UserFailureException
+    {
+        try
+        {
+            getSessionFactory().getCurrentSession().flush();
+            getSessionFactory().getCurrentSession().clear();
+            getExperimentDAO().delete(experimentIds, session.tryGetPerson(), reason);
+        } catch (final DataAccessException ex)
+        {
+            throwException(ex, "Experiment", EntityKind.EXPERIMENT);
+        }
     }
 
     /** if all datasets connected to experiment are placeholders delete them, otherwise do nothing */
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IExperimentDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IExperimentDAO.java
index f691f6341f67456205618ced4fb1b4a938678d0e..cc20cca67b0d609dc78946913ad0357a3689de7c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IExperimentDAO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IExperimentDAO.java
@@ -22,8 +22,10 @@ import java.util.Set;
 
 import org.springframework.dao.DataAccessException;
 
+import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentTypePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ProjectPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SpacePE;
 
@@ -105,4 +107,6 @@ public interface IExperimentDAO extends IGenericDAO<ExperimentPE>
      */
     public void createOrUpdateExperiments(List<ExperimentPE> experiments);
 
+    public void delete(List<TechId> experimentIds, PersonPE tryGetPerson, String reason);
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/AbstractGenericEntityWithPropertiesDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/AbstractGenericEntityWithPropertiesDAO.java
index f63b04a3b15a5a2e5bf0cb8147832fb68cc80b67..43f83cc9c5bbf5c2ad91660e6e657296322ef425 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/AbstractGenericEntityWithPropertiesDAO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/AbstractGenericEntityWithPropertiesDAO.java
@@ -19,14 +19,21 @@ package ch.systemsx.cisd.openbis.generic.server.dataaccess.db;
 import java.util.Collections;
 import java.util.List;
 
+import org.apache.log4j.Logger;
+import org.hibernate.SQLQuery;
+import org.hibernate.StatelessSession;
 import org.springframework.dao.DataAccessException;
 
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDynamicPropertyEvaluationScheduler;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.PersistencyResources;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.db.search.IFullTextIndexUpdateScheduler;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.db.search.IndexUpdateOperation;
+import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.EventType;
 import ch.systemsx.cisd.openbis.generic.shared.dto.IEntityInformationWithPropertiesHolder;
+import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
 
 /**
  * Abstract super class of DAOs for entities that are indexed and contain properties.
@@ -81,4 +88,77 @@ public abstract class AbstractGenericEntityWithPropertiesDAO<T extends IEntityIn
                 getEntityClass(), ids);
     }
 
+    protected void executeDeleteAction(final EntityKind entityKind, final List<TechId> entityIds,
+            final PersonPE registrator, final String reason, final String sqlPermId,
+            final String sqlDeleteProperties, final String sqlAttachmentContentIds,
+            final String sqlDeleteAttachmentContents, final String sqlDeleteAttachments,
+            final String sqlDeleteEntity, final String sqlInsertEvent)
+    {
+        executeStatelessAction(new StatelessHibernateCallback()
+            {
+                public Object doInStatelessSession(StatelessSession session)
+                {
+                    final SQLQuery sqlQueryPermId = session.createSQLQuery(sqlPermId);
+                    final SQLQuery sqlQueryDeleteProperties =
+                            session.createSQLQuery(sqlDeleteProperties);
+                    final SQLQuery sqlQueryDeleteEntity = session.createSQLQuery(sqlDeleteEntity);
+                    final SQLQuery sqlQueryInsertEvent = session.createSQLQuery(sqlInsertEvent);
+                    final SQLQuery sqlQueryAttachmentContentIds =
+                            session.createSQLQuery(sqlAttachmentContentIds);
+                    final SQLQuery sqlQueryDeleteAttachments =
+                            session.createSQLQuery(sqlDeleteAttachments);
+                    final SQLQuery sqlQueryDeleteAttachmentContents =
+                            session.createSQLQuery(sqlDeleteAttachmentContents);
+                    sqlQueryInsertEvent.setParameter("eventType", EventType.DELETION.name());
+                    sqlQueryInsertEvent.setParameter("reason", reason);
+                    sqlQueryInsertEvent.setParameter("registratorId", registrator.getId());
+                    sqlQueryInsertEvent.setParameter("entityType", entityKind.name());
+                    int counter = 0;
+                    for (TechId techId : entityIds)
+                    {
+                        sqlQueryPermId.setParameter("entityId", techId.getId());
+                        final String permIdOrNull = tryGetEntity(sqlQueryPermId.uniqueResult());
+                        if (permIdOrNull != null)
+                        {
+                            // delete properties
+                            sqlQueryDeleteProperties.setParameter("entityId", techId.getId());
+                            sqlQueryDeleteProperties.executeUpdate();
+                            // delete attachments
+                            sqlQueryAttachmentContentIds.setParameter("entityId", techId.getId());
+                            List<Long> attachmentContentIds =
+                                    cast(sqlQueryAttachmentContentIds.list());
+                            if (attachmentContentIds.size() > 0)
+                            {
+                                sqlQueryDeleteAttachments.setParameter("entityId", techId.getId());
+                                sqlQueryDeleteAttachments.executeUpdate();
+                                sqlQueryDeleteAttachmentContents.setParameterList("aIds",
+                                        attachmentContentIds);
+                                sqlQueryDeleteAttachmentContents.executeUpdate();
+                            }
+                            // delete mainEntity
+                            sqlQueryDeleteEntity.setParameter("entityId", techId.getId());
+                            sqlQueryDeleteEntity.executeUpdate();
+                            // create event
+                            sqlQueryInsertEvent.setParameter("description", permIdOrNull);
+                            sqlQueryInsertEvent.setParameter("identifier", permIdOrNull);
+                            sqlQueryInsertEvent.executeUpdate();
+                            if (++counter % 1000 == 0)
+                            {
+                                getLogger().info(
+                                        String.format("%d %ss have been deleted...", counter,
+                                                entityKind.name()));
+                            }
+                        }
+                    }
+                    return null;
+                }
+            });
+
+        // FIXME remove this when we remove the switch to disable trash
+        List<Long> ids = TechId.asLongs(entityIds);
+        scheduleRemoveFromFullTextIndex(ids);
+    }
+
+    abstract Logger getLogger();
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DataDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DataDAO.java
index 1dcebb657f74312cae1edbfbd65ac4aa401259dc..42501093f26d461a3f1c424a3e6dd874abc9aa36 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DataDAO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DataDAO.java
@@ -571,4 +571,10 @@ final class DataDAO extends AbstractGenericEntityWithPropertiesDAO<DataPE> imple
         return transformNumbers2TechIdList(results);
     }
 
+    @Override
+    Logger getLogger()
+    {
+        return operationLog;
+    }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ExperimentDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ExperimentDAO.java
index 2ab18131f7cedf587fc12664d854ad3a05348760..6afafe8987d64766f684c9a2a09ec64c71d488b8 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ExperimentDAO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ExperimentDAO.java
@@ -36,12 +36,17 @@ import ch.systemsx.cisd.common.utilities.MethodUtils;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IExperimentDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.PersistencyResources;
 import ch.systemsx.cisd.openbis.generic.shared.basic.CodeConverter;
+import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPropertyPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentTypePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ProjectPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.SequenceNames;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SpacePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.TableNames;
 
 /**
  * Data access object for {@link ExperimentPE}.
@@ -298,4 +303,42 @@ public class ExperimentDAO extends AbstractGenericEntityWithPropertiesDAO<Experi
         }
     }
 
+    public void delete(final List<TechId> experimentIds, final PersonPE registrator,
+            final String reason) throws DataAccessException
+    {
+        // FIXME delete placeholders
+
+        // NOTE: we use EXPERIMENT_ALL_TABLE, not DELETED_EXPERIMENTS_VIEW because we still want to
+        // be able to directly delete samples without going to trash (trash may be disabled)
+        final String experimentsTable = TableNames.EXPERIMENTS_ALL_TABLE;
+        final String sqlPermId =
+                "SELECT perm_id FROM " + experimentsTable + " WHERE id = :entityId";
+        final String sqlDeleteProperties =
+                "DELETE FROM " + TableNames.EXPERIMENT_PROPERTIES_TABLE
+                        + " WHERE expe_id = :entityId";
+        final String sqlAttachmentContentIds =
+                "SELECT exac_id FROM " + TableNames.ATTACHMENTS_TABLE
+                        + " WHERE expe_id = :entityId";
+        final String sqlDeleteAttachmentContents =
+                "DELETE FROM " + TableNames.ATTACHMENT_CONTENT_TABLE + " WHERE id in (:aIds)";
+        final String sqlDeleteAttachments =
+                "DELETE FROM " + TableNames.ATTACHMENTS_TABLE + " WHERE samp_id = :entityId";
+        final String sqlDeleteSample = "DELETE FROM " + experimentsTable + " WHERE id = :entityId";
+        final String sqlInsertEvent =
+                String.format(
+                        "INSERT INTO %s (id, event_type, description, reason, pers_id_registerer, entity_type, identifier) "
+                                + "VALUES (nextval('%s'), :eventType, :description, :reason, :registratorId, :entityType, :identifier)",
+                        TableNames.EVENTS_TABLE, SequenceNames.EVENT_SEQUENCE);
+
+        executeDeleteAction(EntityKind.EXPERIMENT, experimentIds, registrator, reason, sqlPermId,
+                sqlDeleteProperties, sqlAttachmentContentIds, sqlDeleteAttachmentContents,
+                sqlDeleteAttachments, sqlDeleteSample, sqlInsertEvent);
+    }
+
+    @Override
+    Logger getLogger()
+    {
+        return operationLog;
+    }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ExternalDataDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ExternalDataDAO.java
index 8d3b69ca036078f5c3a349b7ca4c936e4db653af..51281744b2fdd97f733e49aac6fb9e7da7ba5787 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ExternalDataDAO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ExternalDataDAO.java
@@ -545,4 +545,10 @@ final class ExternalDataDAO extends AbstractGenericEntityWithPropertiesDAO<Exter
         scheduleDynamicPropertiesEvaluation(Arrays.asList(entity));
     }
 
+    @Override
+    Logger getLogger()
+    {
+        return operationLog;
+    }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/MaterialDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/MaterialDAO.java
index 470fbe95bebeb64c311d4e9873b50d1533058eea..cd330a09e3710fa4b215d49dc37af963e695b41d 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/MaterialDAO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/MaterialDAO.java
@@ -170,8 +170,7 @@ public class MaterialDAO extends AbstractGenericEntityWithPropertiesDAO<Material
         final String sqlCodeAndType =
                 String.format("SELECT m.code, mt.code as typeCode "
                         + " FROM %s as m, %s as mt WHERE m.id = :mId AND m.maty_id = mt.id",
-                        TableNames.MATERIALS_TABLE,
-                        TableNames.MATERIAL_TYPES_TABLE);
+                        TableNames.MATERIALS_TABLE, TableNames.MATERIAL_TYPES_TABLE);
         final String sqlDeleteProperties =
                 "DELETE FROM " + TableNames.MATERIAL_PROPERTIES_TABLE + " WHERE mate_id = :mId";
         final String sqlDeleteSample =
@@ -182,7 +181,6 @@ public class MaterialDAO extends AbstractGenericEntityWithPropertiesDAO<Material
                                 + "VALUES (nextval('%s'), :eventType, :description, :reason, :registratorId, :entityType, :identifier)",
                         TableNames.EVENTS_TABLE, SequenceNames.EVENT_SEQUENCE);
 
-
         executeStatelessAction(new StatelessHibernateCallback()
             {
                 public Object doInStatelessSession(StatelessSession session)
@@ -215,8 +213,7 @@ public class MaterialDAO extends AbstractGenericEntityWithPropertiesDAO<Material
                                 sqlQueryDeleteSample.setParameter("mId", techId.getId());
                                 sqlQueryDeleteSample.executeUpdate();
                                 // create event
-                                sqlQueryInsertEvent.setParameter("description",
-                                        permId);
+                                sqlQueryInsertEvent.setParameter("description", permId);
                                 sqlQueryInsertEvent.setParameter("identifier", materialCode);
                                 sqlQueryInsertEvent.executeUpdate();
                                 if (++counter % 1000 == 0)
@@ -242,4 +239,10 @@ public class MaterialDAO extends AbstractGenericEntityWithPropertiesDAO<Material
         scheduleRemoveFromFullTextIndex(ids);
     }
 
+    @Override
+    Logger getLogger()
+    {
+        return operationLog;
+    }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/SampleDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/SampleDAO.java
index 096fa4ae1385f3eb9002c585fd5a9e47d2dd0bbe..35c5e8532c446fc893c969bedff223520869e005 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/SampleDAO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/SampleDAO.java
@@ -25,9 +25,7 @@ import java.util.Set;
 import org.apache.log4j.Logger;
 import org.hibernate.Criteria;
 import org.hibernate.FetchMode;
-import org.hibernate.SQLQuery;
 import org.hibernate.Session;
-import org.hibernate.StatelessSession;
 import org.hibernate.criterion.Criterion;
 import org.hibernate.criterion.DetachedCriteria;
 import org.hibernate.criterion.Projections;
@@ -43,9 +41,8 @@ import ch.systemsx.cisd.openbis.generic.server.dataaccess.ISampleDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.PersistencyResources;
 import ch.systemsx.cisd.openbis.generic.shared.basic.CodeConverter;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE;
-import ch.systemsx.cisd.openbis.generic.shared.dto.EventPE.EntityType;
-import ch.systemsx.cisd.openbis.generic.shared.dto.EventType;
 import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePropertyPE;
@@ -386,83 +383,26 @@ public class SampleDAO extends AbstractGenericEntityWithPropertiesDAO<SamplePE>
         // NOTE: we use SAMPLES_ALL_TABLE, not DELETED_SAMPLES_VIEW because we still want to be
         // able to directly delete samples without going to trash (trash may be disabled)
         final String samplesTable = TableNames.SAMPLES_ALL_TABLE;
-        final String sqlPermId = "SELECT perm_id FROM " + samplesTable + " WHERE id = :sId";
+        final String sqlPermId = "SELECT perm_id FROM " + samplesTable + " WHERE id = :entityId";
         final String sqlDeleteProperties =
-                "DELETE FROM " + TableNames.SAMPLE_PROPERTIES_TABLE + " WHERE samp_id = :sId";
+                "DELETE FROM " + TableNames.SAMPLE_PROPERTIES_TABLE + " WHERE samp_id = :entityId";
         final String sqlAttachmentContentIds =
-                "SELECT exac_id FROM " + TableNames.ATTACHMENTS_TABLE + " WHERE samp_id = :sId";
+                "SELECT exac_id FROM " + TableNames.ATTACHMENTS_TABLE
+                        + " WHERE samp_id = :entityId";
         final String sqlDeleteAttachmentContents =
                 "DELETE FROM " + TableNames.ATTACHMENT_CONTENT_TABLE + " WHERE id in (:aIds)";
         final String sqlDeleteAttachments =
-                "DELETE FROM " + TableNames.ATTACHMENTS_TABLE + " WHERE samp_id = :sId";
-        final String sqlDeleteSample = "DELETE FROM " + samplesTable + " WHERE id = :sId";
+                "DELETE FROM " + TableNames.ATTACHMENTS_TABLE + " WHERE samp_id = :entityId";
+        final String sqlDeleteSample = "DELETE FROM " + samplesTable + " WHERE id = :entityId";
         final String sqlInsertEvent =
                 String.format(
                         "INSERT INTO %s (id, event_type, description, reason, pers_id_registerer, entity_type, identifier) "
                                 + "VALUES (nextval('%s'), :eventType, :description, :reason, :registratorId, :entityType, :identifier)",
                         TableNames.EVENTS_TABLE, SequenceNames.EVENT_SEQUENCE);
 
-        executeStatelessAction(new StatelessHibernateCallback()
-            {
-                public Object doInStatelessSession(StatelessSession session)
-                {
-                    final SQLQuery sqlQueryPermId = session.createSQLQuery(sqlPermId);
-                    final SQLQuery sqlQueryDeleteProperties =
-                            session.createSQLQuery(sqlDeleteProperties);
-                    final SQLQuery sqlQueryDeleteSample = session.createSQLQuery(sqlDeleteSample);
-                    final SQLQuery sqlQueryInsertEvent = session.createSQLQuery(sqlInsertEvent);
-                    final SQLQuery sqlQueryAttachmentContentIds =
-                            session.createSQLQuery(sqlAttachmentContentIds);
-                    final SQLQuery sqlQueryDeleteAttachments =
-                            session.createSQLQuery(sqlDeleteAttachments);
-                    final SQLQuery sqlQueryDeleteAttachmentContents =
-                            session.createSQLQuery(sqlDeleteAttachmentContents);
-                    sqlQueryInsertEvent.setParameter("eventType", EventType.DELETION.name());
-                    sqlQueryInsertEvent.setParameter("reason", reason);
-                    sqlQueryInsertEvent.setParameter("registratorId", registrator.getId());
-                    sqlQueryInsertEvent.setParameter("entityType", EntityType.SAMPLE.name());
-                    int counter = 0;
-                    for (TechId techId : sampleIds)
-                    {
-                        sqlQueryPermId.setParameter("sId", techId.getId());
-                        final String permIdOrNull = tryGetEntity(sqlQueryPermId.uniqueResult());
-                        if (permIdOrNull != null)
-                        {
-                            // delete properties
-                            sqlQueryDeleteProperties.setParameter("sId", techId.getId());
-                            sqlQueryDeleteProperties.executeUpdate();
-                            // delete attachments
-                            sqlQueryAttachmentContentIds.setParameter("sId", techId.getId());
-                            List<Long> attachmentContentIds =
-                                    cast(sqlQueryAttachmentContentIds.list());
-                            if (attachmentContentIds.size() > 0)
-                            {
-                                sqlQueryDeleteAttachments.setParameter("sId", techId.getId());
-                                sqlQueryDeleteAttachments.executeUpdate();
-                                sqlQueryDeleteAttachmentContents.setParameterList("aIds",
-                                        attachmentContentIds);
-                                sqlQueryDeleteAttachmentContents.executeUpdate();
-                            }
-                            // delete sample
-                            sqlQueryDeleteSample.setParameter("sId", techId.getId());
-                            sqlQueryDeleteSample.executeUpdate();
-                            // create event
-                            sqlQueryInsertEvent.setParameter("description", permIdOrNull);
-                            sqlQueryInsertEvent.setParameter("identifier", permIdOrNull);
-                            sqlQueryInsertEvent.executeUpdate();
-                            if (++counter % 1000 == 0)
-                            {
-                                operationLog.info(String.format("%d samples have been deleted...",
-                                        counter));
-                            }
-                        }
-                    }
-                    return null;
-                }
-            });
-
-        List<Long> ids = TechId.asLongs(sampleIds);
-        scheduleRemoveFromFullTextIndex(ids);
+        executeDeleteAction(EntityKind.SAMPLE, sampleIds, registrator, reason, sqlPermId,
+                sqlDeleteProperties, sqlAttachmentContentIds, sqlDeleteAttachmentContents,
+                sqlDeleteAttachments, sqlDeleteSample, sqlInsertEvent);
     }
 
     public Set<TechId> listSampleIdsByChildrenIds(final Collection<TechId> children,
@@ -548,4 +488,9 @@ public class SampleDAO extends AbstractGenericEntityWithPropertiesDAO<SamplePE>
         return transformNumbers2TechIdList(results);
     }
 
+    @Override
+    Logger getLogger()
+    {
+        return operationLog;
+    }
 }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExperimentBOTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExperimentBOTest.java
index 936b2da313db7bbae9bc07e2286ced0d2b0d0b18..9521c9550e03c8703b93fd6c1696889a86a68827 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExperimentBOTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExperimentBOTest.java
@@ -42,7 +42,6 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.AttachmentPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.EntityTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.EntityTypePropertyTypePE;
-import ch.systemsx.cisd.openbis.generic.shared.dto.EventPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPropertyPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentTypePE;
@@ -604,40 +603,24 @@ public final class ExperimentBOTest extends AbstractBOTest
     @Test
     public void testDelete()
     {
-        final TechId experimentId = CommonTestUtils.TECH_ID;
-        final ExperimentPE experiment = createExperiment(EXP_CODE);
-        experiment.setId(experimentId.getId());
+        final List<TechId> experimentIds = new ArrayList<TechId>();
+        experimentIds.add(new TechId(1L));
+        experimentIds.add(new TechId(2L));
+        experimentIds.add(new TechId(3L));
         final String reason = "reason";
-
-        prepareAnyDaoCreation();
-        prepareTryToLoadOfExperimentWithId(experiment);
         context.checking(new Expectations()
             {
                 {
-                    PersonPE person = EXAMPLE_SESSION.tryGetPerson();
-                    EventPE event = ExperimentBO.createDeletionEvent(experiment, person, reason);
-                    one(eventDAO).persist(event);
-                    one(experimentDAO).delete(experiment);
+                    PersonPE registrator = EXAMPLE_SESSION.tryGetPerson();
+                    one(experimentDAO).delete(experimentIds, registrator, reason);
                 }
             });
 
         final ExperimentBO expBO = createExperimentBO();
-        expBO.deleteByTechIds(Collections.singletonList(experimentId), reason);
+        expBO.deleteByTechIds(experimentIds, reason);
         context.assertIsSatisfied();
     }
 
-    private void prepareTryToLoadOfExperimentWithId(final ExperimentPE experiment)
-    {
-        context.checking(new Expectations()
-            {
-                {
-                    one(experimentDAO).tryGetByTechId(with(new TechId(experiment.getId())),
-                            with(any(String[].class)));
-                    will(returnValue(experiment));
-                }
-            });
-    }
-
     private static ExperimentPE createExperiment(String code)
     {
         ExperimentIdentifier ident =