NHibernate - Как обновить более одного логического поля одновременно - PullRequest
0 голосов
/ 02 декабря 2011

Я использую NHibernate в создаваемом веб-приложении. Пользователь может подписаться на ноль или более списков рассылки (всего их 8). Это представлено на экране флажком для каждого списка рассылки.

Я бы хотел использовать NHibernate, чтобы обновить их за один раз. Очень простой SQL-запрос будет выглядеть так:

update mail_subscriptions set subscribed = true where mailing_list_id in (21,14,15,19) and user_id = 'me'

Каков самый чистый способ выполнить это обновление через NHibernate, чтобы я мог совершить одну поездку в базу данных? Заранее спасибо

JP

Ответы [ 2 ]

2 голосов
/ 02 декабря 2011

Я думаю, что функция NHibernate, которую вы ищете, известна как Исполняемый файл DML .

У Айенде есть запись в блоге, где приводится пример на http://ayende.com/blog/4037/nhibernate-executable-dml.

В зависимости от ваших имен ваших сущностей и их свойств, и при условии, что у вас есть переменная экземпляра ISession под названием session, вам нужно будет выполнить HQL-запрос примерно так:

session.CreateQuery("update MailSubscriptions set Subscribed = true where MailingList.Id in (21,14,15,19) and User.Id = 'me'")
    .ExecuteUpdate();

Теперь, сказав это, я думаюв описываемом вами сценарии использования (обновление нескольких записей в коллекции в едином агрегированном корне) нет необходимости использовать исполняемый файл DML.Марк Перри имеет правильную идею - вы должны просто изменить логические значения для соответствующих объектов и очистить сеанс обычным способом.Если пакетная обработка ADO.NET настроена надлежащим образом, дочерние записи будут вызывать отправку нескольких операторов обновления в СУБД за один вызов базы данных.

2 голосов
/ 02 декабря 2011

NHibernate, возможно, не сможет обновить mail_subscriptions, как вы показали выше, но он может сделать это за одну поездку в БД с помощью пакетных запросов.

В этом примере рассматривается Subscriptions сопоставленный как HasMany с использованием Component, хотя примерно такой же метод можно использовать, если сопоставление было просто равным HasMany. Я также предполагаю, что у каждого пользователя уже есть строки в таблице mail_subscriptions для каждого списка рассылки, установленного на false для subscribed.

public class User{
    public virtual string Id {get; set;}
    public virtual IList<MailSubscription> Subscriptions {get; set;}
}

public class MailSubscription{
    public virtual int ListId {get; set;}
    public virtual bool Subscribed {get; set;}
}

public void UpdateSubscriptions(string userid, int[] mailingListIds){
    var user = session.Get<User>(userid);
    foreach(var sub in 
       user.Subscriptions.Where(x=> mailingListIds.Contains(x.ListId))){
        sub.Subscribed=true;
    }
    session.Update(user);
}

Теперь, когда единица работы завершится, вы должны увидеть, как SQL, полученный таким образом, отправляется в одну поездку в БД.

update mail_subscriptions set subscribed=true where user_id='me' and listid=21
update mail_subscriptions set subscribed=true where user_id='me' and listid=14
update mail_subscriptions set subscribed=true where user_id='me' and listid=15
update mail_subscriptions set subscribed=true where user_id='me' and listid=19
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...