我在我正在构建的Web应用程序中使用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
答案 0 :(得分:2)
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
答案 1 :(得分:2)
我认为您寻求的NHibernate功能称为可执行DML 。
Ayende有一篇博客文章,在http://ayende.com/blog/4037/nhibernate-executable-dml给出了一个例子。
根据您的实体名称及其属性,并假设您有一个名为session的ISession实例变量,您需要执行以下类似的HQL查询:
session.CreateQuery("update MailSubscriptions set Subscribed = true where MailingList.Id in (21,14,15,19) and User.Id = 'me'")
.ExecuteUpdate();
现在,我已经说过,我认为在您描述的用例中(在单个聚合根上更新集合中的少数条目),不需要使用可执行DML。 Mark Perry有正确的想法 - 你应该简单地修改相应实体上的布尔值并以通常的方式刷新会话。如果ADO.NET批处理配置正确,则子条目将导致在单个数据库调用中将多个更新语句发送到RDBMS。