【问题标题】:Update method without HQL mode in NHibernateNHibernate 中没有 HQL 模式的更新方法
【发布时间】:2014-10-01 17:44:39
【问题描述】:

我想在 NHibernate 中创建一个带有限制(where 子句)的 Update 方法,但我不想做 HQL 模式。

例如,我的 SQL 查询:

"update NFE set SEFAZ_STATUS_DATA=@SEFAZ_STATUS_DATA,MENSAGEM_ERRO=@MENSAGEM_ERRO"

不使用 HQL 怎么办?

这行得通吗?

public virtual T Alterar(List<ICriterion> lstCriterios, T entity)
{
    try
    {
        using (ISession session = SessionFactory.OpenSession())
        {
            ICriteria criterio = session.CreateCriteria(typeof(T));

            foreach (ICriterion cri in lstCriterios)
            {
                criterio.Add(cri);
            }

            session.Update(entity);

            return entity;
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

【问题讨论】:

    标签: c# nhibernate fluent-nhibernate hql


    【解决方案1】:

    一般来说,有两种方法可以执行更新。一种是基于会话的,第二种是由 DML 表示的。

    9.4.1. Updating in the same ISession

    事务性持久实例(即,由 ISession 加载、保存、创建或查询的对象)可以由应用程序操作,并且在刷新 ISession 时,对持久状态的任何更改都将保持不变(本章稍后讨论)。所以最直接的更新对象状态的方法是 Load() 它,然后直接操作它,同时 ISession 是打开的...

    因此,在我们的例子中,我们可以使用任何类型的查询将实体(Criteria、QueryOver、Query)加载到会话中。这意味着,不需要 HQL。

    然后,所有对象都将在服务器/应用程序层 (C#) 上更新,然后在刷新会话后。所有更改都将保留。

    这种方法需要大量后台处理(从 SQL 选择创建实体...创建 UPDATE 语句...)但对于 NHiberante/ORM 来说非常原生

    using (ISession session = SessionFactory.OpenSession())
    {
        var criteria = session.CreateCriteria<T>();
    
        // I. use criteria to find what should be changed    
        foreach (var cri in lstCriterios)
        {
            criterio.Add(cri);
        }
    
        // II. load the searched
        var list = session.List<T>();
    
        // III. update entities in runtime
        foreach(var entity in list)
        {
           entity.Property1 = newValue1;
           entity.Property2 = newValue2;
           ...
        }
    
        // IV. UPDATE == flush
        session.Flush();
    }
    

    13.3. DML-style operations

    如前所述,自动和透明的对象/关系映射与对象状态的管理有关。这意味着对象状态在内存中可用,因此直接在数据库中操作(使用 SQL 数据操作语言 (DML) 语句:INSERT、UPDATE、DELETE)数据不会影响内存中的状态。然而,NHibernate 提供了用于批量 SQL 样式 DML 语句执行的方法,这些语句通过 Hibernate 查询语言 (HQL) 执行...

    在这种情况下,我们确实可以访问最有效的 UPDATE - 直接在数据库服务器上执行,无需任何实体加载。见例子:

    ISession session = sessionFactory.OpenSession();
    ITransaction tx = session.BeginTransaction();
    
    string hqlUpdate = "update Customer c set c.name = :newName where c.name = :oldName";
    // or string hqlUpdate = "update Customer set name = :newName where name = :oldName";
    int updatedEntities = s.CreateQuery( hqlUpdate )
            .SetString( "newName", newName )
            .SetString( "oldName", oldName )
            .ExecuteUpdate();
    tx.Commit();
    session.Close();
    

    虽然这种方法给我们带来了出色的性能,但它基于 HQL(与上述要求相反)...

    总结:使用 NHibernate,我们可以使用强大的查询而不使用 HQL 将数据加载到会话中,在 C# 中操作它们,一个一个地持久化更改......或者我们可以使用 HQL 创建一个 DML 语句,并直接在 UPDATE 上执行服务器

    另请参阅:NHibernate – Executable DML Ayende

    【讨论】:

    • 这种情况下,我想创建一个可以传递参数和实体的泛型方法,然后泛型方法将根据报告的参数执行更新,在我的情况下是一个标准列表。根据我向您展示的使用 Session 而不是 HQL 的示例,您知道我该怎么做吗?所以我不需要写很多命令更新...
    • 我刚刚用方法内容的草稿更新/扩展了我的答案......只需 1)创建标准 2)加载结果 3)加载更新 4)调用刷新......这将起作用。事实上,它是非常简化的 WRITE 操作的标准方式,我确实在日常基础上执行。以更复杂的方式,这几乎是标准的 UPDATE 方法......它有帮助吗?
    • 在你扩展后,答案比我需要的更接近,但在我的情况下,因为我需要提供一个通用实体 (T) 作为参数,我无法运行摘录 III ...
    • Criteria API 绝对适合通用 T... 你会收到一些搜索参数,例如代表名称的字符串,您将使用它们作为.Add(Restriction.PropertyEa("FirstName", firstName")...尝试玩弄。同样的方式你可以建立非常强大的处理。另外,请阅读doc。我会说这应该给你一些想法如何做到这一点。祝 NHiberante 好运
    猜你喜欢
    • 2011-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多