-2

我只想使用 NHibernate QueryOver 语法更新包含 N 列的表中的 N-1 列。

我试过的查询是这样的。

    public T UpdatePost(Object DateUpdated, object DateExpires, object Id)
    {
        using (var session=sessionFactory.OpenSession())
        {
            using (var transaction=session.BeginTransaction())
            {
                session.Update(DateUpdated, Id);
                session.Update(DateExpires, Id);
                transaction.Commit();
                return session.Get<T>(Id);
            }
        }
    }

调用方法是

obj.UpdatePost(DateTime.Now, DateTime.Now.AddDays(30), 3);

错误是

你的映射有问题。您可能正在尝试将 System.ValueType 映射到 NHibernate 不允许的,或者您错误地使用了映射到 . ValueType (System.DateTime) 不能与 IdentityKey 一起使用。

如何做到这一点?

4

2 回答 2

2

你的UpdatePost方法没有意义。NHibernatesession.Update需要一个应该更新的实体对象。您尝试使用的重载文档是:

更新与给定标识符关联的持久状态。

第一个参数应该是一个完整的实体对象。

如果您尝试分析您的代码,NHibernate 无法知道您要更新哪个实体。Update方法不是通用的,Session. 您只是想给它一个日期值和一个 ID。NHibernate 怎么知道要更新哪个表和哪个列?

为了使用 NHibernate 进行部分更新,您需要使用HQL 更新查询(DML 样式的操作)。

以下是您的情况:

public T UpdatePost(Object DateUpdated, object DateExpires, object Id)
{
    using (var session=sessionFactory.OpenSession())
    {
        using (var transaction=session.BeginTransaction())
        {
            string hqlUpdate = 
                 "update Post p set p.DateUpdated = :dateUpdated, p.DateExpires = :dateExpires where p.id = :id";
            session.CreateQuery(hqlUpdate)
                   .SetDateTime("dateUpdated", DateUpdated)
                   .SetDateTime("dateExpires", DateExpires)
                   .SetParameter("id", Id)
                   .ExecuteUpdate();
            transaction.Commit();
            return session.Get<T>(Id);
        }
    }
}

附带说明一下,由于您在更新后已经获取了实体本身,因此您可以简单地先加载实体,更改其属性并保存它。您仍然会有两个数据库操作。

public T UpdatePost(DateTime DateUpdated, DateTime DateExpires, object Id)
{
    using (var session=sessionFactory.OpenSession())
    {
        using (var transaction=session.BeginTransaction())
        {
            T post = session.Get<T>(Id);
            post.DateUpdated = DateUpdated;
            post.DateExpires = DateExpires;
            session.Update(post);
            transaction.Commit();
            return post;
        }
    }
}

如果你真的想强制 NHibernate 只更新被改变的列,你可以在类映射声明中指定 dynamic-update="true" 。

动态更新(可选,默认为 false):指定 UPDATE SQL 应在运行时生成,并且仅包含值已更改的那些列。

于 2012-06-24T07:54:10.253 回答
0

这将是最佳解决方案,因为 SetDateTime 仅接受 DateTime 类型作为其参数值。并且在一般声明此方法时,我们必须根据其实体类型格式化查询。

public T UpdatePost(DateTime DateUpdated, DateTime DateExpires, object Id) <-- DateTime parameters
        {
            using (var session = sessionFactory.OpenSession())
            {
                using (var transaction = session.BeginTransaction())
                {
                    string hqlUpdate = string.Format(
                 "update {0} p set p.DateUpdated = :dateUpdated, p.DateExpires = :dateExpires where p.id = :id", typeof(T)); <-- passing the type of the entity.
                    session.CreateQuery(hqlUpdate)
                           .SetDateTime("dateUpdated",DateUpdated)
                           .SetDateTime("dateExpires", DateExpires)
                           .SetParameter("id", Id)
                           .ExecuteUpdate();
                    transaction.Commit();
                    return session.Get<T>(Id);
                }
            }
        }
于 2012-06-24T18:07:52.427 回答