如何使用NHibernate向更新命令添加其他条件?

如何使用NHibernate向更新命令添加其他条件?,nhibernate,Nhibernate,在这种情况下,消息表有一个主键(Id)和一个外键(Site)。任何站点都可以创建消息记录,但只有创建该记录的站点才能更新它。问题是,默认情况下,它将根据Id而不是Id和站点进行更新。我可以将主键更改为由id和站点组成的复合/复合id,或者使用本机SQL;然而,我想知道是否有一种方法可以添加额外的更新标准 例如,这是默认情况下得到的结果: public void MessageUpdate(Message oneMessage) { using(ISession session = Ses

在这种情况下,消息表有一个主键(Id)和一个外键(Site)。任何站点都可以创建消息记录,但只有创建该记录的站点才能更新它。问题是,默认情况下,它将根据Id而不是Id和站点进行更新。我可以将主键更改为由id和站点组成的复合/复合id,或者使用本机SQL;然而,我想知道是否有一种方法可以添加额外的更新标准

例如,这是默认情况下得到的结果:

public void MessageUpdate(Message oneMessage) { using(ISession session = SessionFactory.OpenSession()) using(ITransaction trans = session.BeginTransaction()) { session.Update(oneMessage); trans.Commit(); } } 公共无效消息更新(消息oneMessage) { 使用(ISession session=SessionFactory.OpenSession()) 使用(ITransaction trans=session.BeginTransaction()) { 会话更新(oneMessage); trans.Commit(); } } 那么,在NHibernate中如何在不创建复合id或使用本机SQL的情况下实现这一点:

Update MessageTable set MessageStatus = 2 where Id = ? and Site = ?; 更新MessageTable set MessageStatus=2,其中Id=?和地点=?;
我对你的问题的理解是,该规则是一项业务要求,因此,可能NHibernate不适用于该规则。您可以尝试在更新事件上实现侦听器:


另一种解决方案是用update将属性标记为false,以防止更改记录的站点?(请参见生成的属性)

您不能直接在NHibernate中执行此操作,但可以将更新方法更改为:

public void MessageUpdate(Message oneMessage, string currentSite)
{
    if (oneMessage.Site != currentSite)
    {
        throw new Exception("meaningful error message");
    }
    using(ISession session = SessionFactory.OpenSession())
    using(ITransaction trans = session.BeginTransaction())
    {
        session.Update(oneMessage);
        trans.Commit();
    }
}

假设Site是一个字符串和Message属性。此外,如果出现异常,您还需要将更新包装为try..catch并回滚事务。

我想我最初问题的简短答案是,您不能向更新添加条件。您可以按照我最初的建议使用本机SQL来处理这种情况:

更新MessageTable set MessageStatus=2,其中Id=?和地点=


或者,您也可以按照Jamie Ide的建议解决这个问题,但需要对数据库进行额外的查询才能提取原始消息。

唯一的问题是记录仍然是根据Id更新的,因此站点可能是错误的&仍然更新错误的记录。验证站点的唯一正确方法是查询数据库中的消息,检查站点id,然后将其与允许用户访问的站点id进行比较。这将需要对数据库进行额外的访问,这是我试图避免的。复合id将通过要求使用站点id和id来解决此问题。目前,我已经求助于本机SQL来解决这个问题,但我希望我可以为更新添加其他条件。“因此,该站点可能是错误的&仍然更新错误的记录。”——如果使用类似于我作为示例编写的方法执行更新,则不会。如果登录被破坏,攻击者只能执行应用程序允许的操作。如果应用程序。或者服务器被破坏,攻击者可以绕过此方法或编写自己的SQL,那么唯一的保护就是频繁备份。Jamie,感谢您的回复。我想我最初问题的简短答案是,您不能向更新添加条件。在您的示例中,我仍然需要查询数据库中的原始消息,更新status字段,不使用站点id,然后使用允许用户访问的消息和当前站点调用MessageUpdate方法。这当然会起作用,但使用本机sql可以避免查询,并使用where语句验证用户站点id是否与记录中的站点id匹配。如果没有更新记录,我可以采取各种措施。安全规则是,“用户不能更新他们无权访问的站点的消息记录”。如果用户登录被破坏,攻击者只能破坏与给定站点相关的消息。如果我有额外的更新标准,我可以从用户那里获取传入ID和状态,并从数据库中获取他们的站点ID。然后,我可以使用id、siteid和status构建一个update语句。因此,无权访问某个站点的用户永远不会弄乱另一个站点的记录。顺便说一句,您不需要在代码中使用session.Update。更多关于这个