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?谷歌也很难,因为谷歌消除了 -1

4

1 回答 1

1

NHibernate 需要检查其内部生成的 SQL 命令的结果。您的自定义实现(存储过程)也需要/应用相同的内容,因为它的处理方式相同。

但是有很好的解决方案。在此处阅读更多内容17.3。用于创建、更新和删除的自定义 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 回答