0

標準の SqlInsert で標準の INSERT を使用する場合に機能するコードによる NHibernate マッピングがあります

class ProductTranslationMapping : ClassMapping<ProductTranslation>
{
    public ProductTranslationMapping ()
    {
        .
        .
        SqlInsert ("insert into product_translation(product_id, language_code, product_name, product_description) values(?,?,?,?)");

        .
        .       
    }
}

ただし、Postgresqlストアドプロシージャを使用したいので、挿入と更新の両方が同じルーチンを使用できます

class ProductTranslationMapping : ClassMapping<ProductTranslation>
{
    public ProductTranslationMapping ()
    {

        .       
        .
        SqlInsert ("select merge_product_translation(?,?,?,?)");
        SqlUpdate ("select merge_product_translation(?,?,?,?)");
        .
        .       
    }
}

ただし、Postgresql 関数を使用すると、エラーが発生します。

Unhandled Exception:
NHibernate.StaleStateException: Unexpected row count: -1; expected: 1
  at NHibernate.AdoNet.Expectations+BasicExpectation.VerifyOutcomeNonBatched (Int32 rowCount, IDbCommand statement) [0x00000] in <filename unknown>:0 
  at NHibernate.AdoNet.NonBatchingBatcher.AddToBatch (IExpectation expectation) [0x00000] in <filename unknown>:0 
  at NHibernate.Persister.Entity.AbstractEntityPersister.Insert (System.Object id, System.Object[] fields, System.Boolean[] notNull, Int32 j, NHibernate.SqlCommand.SqlCommandInfo sql, System.Object obj, ISessionImplementor session) [0x00000] in <filename unknown>:0 
[ERROR] FATAL UNHANDLED EXCEPTION: NHibernate.StaleStateException: Unexpected row count: -1; expected: 1
  at NHibernate.AdoNet.Expectations+BasicExpectation.VerifyOutcomeNonBatched (Int32 rowCount, IDbCommand statement) [0x00000] in <filename unknown>:0 
  at NHibernate.AdoNet.NonBatchingBatcher.AddToBatch (IExpectation expectation) [0x00000] in <filename unknown>:0 
  at NHibernate.Persister.Entity.AbstractEntityPersister.Insert (System.Object id, System.Object[] fields, System.Boolean[] notNull, Int32 j, NHibernate.SqlCommand.SqlCommandInfo sql, System.Object obj, ISessionImplementor session) [0x00000] in <filename unknown>:0 

それが役立つ場合は、これが私の Postgresql ストアド プロシージャです。

create or replace function merge_product_translation(p_product_id int, p_language_code text, p_product_name text, p_product_description text) returns int
as
$$
begin
    if not exists(select * from product_translation where product_id = p_product_id and language_code = p_language_code) then       
        insert into product_translation(product_id, language_code, product_name, product_description)
        values(p_product_id, p_language_code, p_product_name, p_product_description);
    else        
        update product_translation set
            product_name = p_product_name,
            product_description = p_product_description
        where product_id = p_product_id and language_code = p_language_code;    
    end if;

    return 1;

end;
$$
language 'plpgsql';

私も次のことを試しましたが、まだ運が悪く、すべてにエラーがあります:

SqlInsert ("perform merge_product_translation(?,?,?,?)");
SqlInsert ("call merge_product_translation(?,?,?,?)");  
SqlInsert ("{call merge_product_translation(?,?,?,?)}");        

エラーを回避するには、何を使用すればよいunexpected row count of -1ですか? また、Google は -1 を削除するため、Google で検索するのも困難です。

4

1 に答える 1

1

NHibernate は、内部で生成された SQL コマンドの結果を確認する必要があります。同じように扱われるため、カスタム実装 (ストアド プロシージャ) にも同じことが必要/適用されます。

しかし、良い解決策があります。詳細はこちら17.3. create、update、delete のカスタム SQL

抽出物:

デフォルトでは、ストアド プロシージャは、NHibernate によって生成された SQL と同じ数の行に影響を与える必要があります。NHibernate は IDbCommand.ExecuteNonQuery を使用して、影響を受ける行数を取得します。このチェックは、sql-insert 要素で check="none" 属性を使用して無効にすることができます。

解決策: ... マッピングを次のように調整します。

<sql-insert check="none" >..</sql-insert>
<sql-update check="none" >..</sql-update>
于 2013-05-19T18:56:08.707 に答える