-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);

エラーは

マッピングに問題があります。おそらく、NHibernateが許可していないにSystem.ValueTypeをマップしようとしているか、にマップされているIDictionaryを誤って使用しています。ValueType(System.DateTime)はIdentityKeyでは使用できません。

これを達成する方法は?

4

2 に答える 2

2

あなたのUpdatePost方法は意味がありません。Hibernatesession.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);
        }
    }
}

ちなみに、更新後に既にエンティティ自体を取得しているため、最初にエンティティをロードし、そのプロパティを変更して保存するだけです。それでも 2 つのデータベース操作があります。

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" を指定できます

dynamic-update (オプション、デフォルトは 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 に答える