2009-08-25 3 views
13

Это должен быть простой вопрос. Учитывая критерии, как удалить объекты, удовлетворяющие критериям?Как удалить объекты NHibernate с помощью критериев?

Обоснование:

HQL и критерии NH являются NHibernate конкретные конструкции и, как таковые, они на стороне сервера, DAL детали реализации. Я не хочу, чтобы они «просачивались» на клиентскую сторону. Таким образом, наша клиентская сторона предоставляет выражения LINQ для обработки сервера. До сих пор запросы, в которых запросы на выбор и LINQ to NHibernate имели дело с ними, были прекрасными.

Однако необходимо выполнить операцию пакетного удаления. Как обычно, клиентская сторона предоставляет выражение LINQ, и сервер должен удалить объекты, удовлетворяющие выражению. К сожалению, LINQ to NHibernate здесь не поможет. Самое большее, что он может сделать, это перевести данное выражение LINQ в критерии NHibernate.

В любом случае, это история. Я хочу подчеркнуть, что клиентская сторона вообще не знает об NHibernate, и мне нравится, чтобы она оставалась таким образом.

P.S.

Я использую NH 2.1

ответ

-3

В вашем хранилище/дао/PersistenceManager/любой класс:

public IEnumerable<T> FindAll(DetachedCriteria criteria) 

     { 

      return criteria.GetExecutableCriteria(Session).List<T>(); 

     } 

, а затем пост

public void Delete(DetachedCriteria criteria) 

     { 

      foreach (T entity in FindAll(criteria)) 

      { 

       Delete(entity); 

      } 

     } 

знакомства Дэви Брайона Data Access with NHibernate.

Edit:

Насколько я знаю, если вы хотите использовать критерии, которые нужно загрузить объекты и перебирать их, чтобы удалить их. В качестве альтернативы можно использовать HQL или передать SQL в сеанс.

+6

Мне не нравится этот метод, хотя при работе с большим количеством объектов, поскольку он требует выборки всех сущностей из базы данных прежде, чем их можно будет удалить. –

+3

Это правда, вам не нужно использовать HQL для выдачи SQL-запроса «УДАЛИТЬ ОТ ГДЕ»? – DanB

+2

Ребята, вы не серьезно. Должен быть лучший способ! – mark

7

Вы можете использовать критерии для выбора идентификаторов ваших элементов, объединения их в строку и использования HQL для их удаления?

Что-то вроде:

public void Delete(ICriteria criteria, string keyName, string tableName) 
{ 
    criteria.setProjection(Projections.Attribute(keyName)); 
    IList<int> itemIds = criteria.List<int>(); 

    string collection = string.Join(",", Array.ConvertAll<int, string>(itemIds, Convert.ToString)); 

    Session.HQL(string.Format("delete from {0} where {1} in ({2})", tableName, keyName, collection); 
} 

Этот код не был проверен или составлен (в частности, я не уверен в разделе HQL), но я думаю, что вы получили эту идею: мы не Позовите целые объекты благодаря проекции, но только индексы.

+1

Означает ли это две круглые поездки в базу данных? Если да, то это недостаточно, потому что собственный SQL делает это просто в одном. – mark

+1

Все еще лучше, чем N + 1 ... Я не могу лучше понять критерии:/ – madprog

3

Проще говоря, до 2.1.2 вы не можете.

Однако, если вы можете перевести выражение LINQ в HQL (или ICriteria в HQL), то вы можете использовать перегруженный метод ISession.Delete(), который использует пройденную строку HQL.

+0

Я знаю, что могу, но не кажется странным, что LINQ to NHibernate переводит LINQ в критерии, а не в HQL, хотя последний предполагается быть более мощным? Может быть, это не так просто. Мне бы хотелось увидеть рабочий прототип ... – mark

+0

Я бы не сказал, что HQL более мощный, чем Criteria, или наоборот. Это всего лишь две разные конструкции, обычно с разными целями: HQL для разовых конкретных запросов и критериев для построения запросов, избегающих всех проблем с конкатенацией строк, модульной поддержки через DetachedCriteria и по-прежнему ближе к вашему сопоставлению. Поэтапная конструкция также сладка, но на самом деле редко используется. Во всяком случае, я не использую LINQ для nhibernate -yet- поэтому у меня нет никаких примеров. Тем не менее, пока новая версия не будет поддерживать то, что вы хотите, критерии относятся только к отдельным операторам – Jaguar

-5

Я знаю, что это старый вопрос, но для аргументации; если один использует шаблон репозитория вы можете объявить метод удаления, который выполняет следующие действия:

public void Delete(System.Linq.Expressions.Expression<System.Func<TEntity, bool>> predicate) 
{ 
    var entities = _session.Query<TEntity>().Where(predicate); 
    foreach (var entity in entities) 
     _session.Delete(entity); 
} 

Обратите внимание на код, используя выражения для того, чтобы интерфейс хранилища, чтобы быть достаточно общим, так что вы можете реализовать, например, Entity Framework хранилище.

+4

Не совсем. То, что вы делаете, это использовать выражение для извлечения сущностей, а затем вы удаляете их один за другим. Это не удаление сущностей по выражению. Я имею в виду, что у него есть собственный API, который получает выражение, преобразует его в соответствующий оператор SQL-запроса и затем удаляет все объекты за один раз. – mark

+2

Это требует большого предупреждения о том, как это не будет хорошо, когда у вас много объектов. –

Смежные вопросы