[INFO] NHibernate storedproc params mapping (ord NOT req)
От: снежок Россия  
Дата: 20.06.08 09:23
Оценка:
В документации и статьях описано как произвести маппинг объектов на хранимые процедуры (CRUD).
Описано также что существуют некоторые ограничения, так например, порядок следования параметров в хп должен соответветствовать порядку в котором NHibernate генерит запрос к БД.
Исходя из этого чато делаются выводы:
1. что с помощью NHibernate можно организовать маппинга на хп, если они (хп) создаются с "чистого листа" и если определять параметры в хп в том же порядке в котором генерит NHibernate.
2. NHibernate не подходит для маппинга объектов на хп, разработанные без оглядки на NHibernate

Однако, это не совсем так, по крайней мере для MSSQL.
MSSQL поддерживает синтаксис вызова хп, в котором можно явно задать имя параметра, таким образом, порядок следования параметров в синтаксисе вызова не обязательно должен соответствовать порядку параметров в определении хп.
пример, подобного синтаксиса:
/*exec @RET_CODE = CreateDocument*/
  exec CreateDocument
       @Title           = ?
      ,@FileName        = ?
      ,@FileExtension   = ?
      ,@Revision        = ?
      ,@ChangeNumber    = ?
      ,@Status          = ?
      ,@DocumentSummary = ?
      ,@ModifiedDate    = ?
      ,@DocumentID      = ?

Я всегда стараюсь использовать именно такой вызов хп, потому что этот синтаксис более строгий и более информативный, а поэтому предупреждает появление ошибок (в частности ошибок несоответствия следования параметров).
Хранимая процедура может быть определена следующим образом:


CREATE PROCEDURE CreateDocument(
--<ParamDefBlock>
 @DocumentID                      int                   = null out
,@Title                           nvarchar(50)          = null
,@FileName                        nvarchar(400)         = null
,@FileExtension                   nvarchar(8)           = null
,@Revision                        nchar(5)              = null
,@ChangeNumber                    int                   = null
,@Status                          tinyint               = null
,@DocumentSummary                 nvarchar(Max)         = null
,@ModifiedDate                    datetime              = null
--</ParamDefBlock>
)
AS
BEGIN
    SET NOCOUNT ON
    --<DeclareBlock>
    --<DeclareSysVarBlock>
    declare     
             @RET_CODE            int
            ,@ERROR_CODE            int
            ,@TRAN_CHECK            int
    --</DeclareSysVarBlock>
    --<DeclareVarBlock>
    --</DeclareVarBlock>
    --</DeclareBlock>
    --<PrepareTranBlock>
    set @TRAN_CHECK    = case when @@TRANCOUNT > 0 or @@OPTIONS & 2 > 0 then 1 else 0 end
    select    
             @RET_CODE        = 0
            ,@ERROR_CODE    = 0
    if @TRAN_CHECK = 0 BEGIN TRAN
    --</PrepareTranBlock>
    
    --<InsertBlock>
    INSERT INTO Production.Document(Title, FileName, FileExtension, Revision, ChangeNumber, Status, DocumentSummary, ModifiedDate)
                VALUES(@Title, @FileName, @FileExtension, @Revision, @ChangeNumber, @Status, @DocumentSummary, @ModifiedDate)
    --</InsertBlock>
    
    set @ERROR_CODE = @@ERROR
    if (@ERROR_CODE <> 0) or (@RET_CODE <> 0) GOTO UNDO
    --<SuccBlock>
    SUCC:
            SET @DocumentID = SCOPE_IDENTITY()
            SELECT @DocumentID as DocumentID
        if (@TRAN_CHECK = 0) and (@@TRANCOUNT > 0) COMMIT TRAN
        RETURN(0)
    --</SuccBlock>

    --<UndoBlock>
    UNDO:
        if (@@TRANCOUNT > 0)
            if @TRAN_CHECK = 0 ROLLBACK TRAN 
        RETURN(1)
    --</UndoBlock>
END


Маппинг в NHibernate может выглядеть так, как показано ниже.
В определении маппинга используем синтаксис с явным определением имен параметров.
Параметр, соответствующий id (DocumentID) определяем последним в списке (так требуется для корректной работы NHibernate).
Порядок параметров при вызове из NHibernate не соответствует порядку параметров в определении хп, однако решение работоспособно и мы добились некоторой развязки NHibernate и хп.

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class name="WebApplication.Document, WebApplication" table="Production.Document">
    <id name="DocumentID" column="DocumentID">
      <generator class="identity" />
    </id>
    <property name="Title" />
    <property name="FileName" />
    <property name="FileExtension" />
    <property name="Revision" />
    <property name="ChangeNumber" />
    <property name="Status" />
    <property name="DocumentSummary" />
    <property name="ModifiedDate" />
    <property name="DocumentID" />
    <sql-insert check="none">
      exec xsp_Ins_Document 
       @Title           = ?
      ,@FileName        = ?
      ,@FileExtension   = ?
      ,@Revision        = ?
      ,@ChangeNumber    = ?
      ,@Status          = ?
      ,@DocumentSummary = ?
      ,@ModifiedDate    = ?
      ,@DocumentID      = ?
    </sql-insert>
  </class>
</hibernate-mapping>
Re: [INFO] NHibernate storedproc params mapping (ord NOT req
От: снежок Россия  
Дата: 20.06.08 09:25
Оценка:
С>    <sql-insert check="none">
С>      exec CreateDocument 
С>       @Title           = ?
С>      ,@FileName        = ?
С>      ,@FileExtension   = ?
С>      ,@Revision        = ?
С>      ,@ChangeNumber    = ?
С>      ,@Status          = ?
С>      ,@DocumentSummary = ?
С>      ,@ModifiedDate    = ?
С>      ,@DocumentID      = ?
С>    </sql-insert>
Re: [INFO] NHibernate storedproc params mapping (ord NOT req
От: D.Triton Украина  
Дата: 20.06.08 13:15
Оценка:
Добрый день.
У меня вопрос в догонку.

Не пробовали-ли вы делать custom-mapping для отношения многие-ко-многим на хранимых процедурах?

У меня почему-то в итоге происходит NullReferenceException внутри коллекции, которые
использует NHibernate для хранения соотв. множеств записей при реализации указанного отношения независимо от того, использую я lazy-load или нет.
(Происходит именно с many-to-many).

Спасибо.
Re[2]: [INFO] NHibernate storedproc params mapping (ord NOT
От: снежок Россия  
Дата: 20.06.08 14:25
Оценка:
DT>Не пробовали-ли вы делать custom-mapping для отношения многие-ко-многим на хранимых процедурах?

Не пробовал, я всегда стараюсь такие связи либо развернуть, либо избежать их.
Re: [INFO] NHibernate storedproc params mapping (ord NOT req
От: D.Triton Украина  
Дата: 24.06.08 09:04
Оценка:
Добрый день.

Вот уже сутки борюсь с получением id-шника после insert-a

Меня смущает указанный вами
<generator class="identity" />

У меня в этом случае вызывается "прямой" insert в таблицу, а потом select SCOPE_IDENTITY()
Re[2]: [INFO] NHibernate storedproc params mapping (ord NOT
От: Нахлобуч Великобритания https://hglabhq.com
Дата: 24.06.08 09:23
Оценка:
Здравствуйте, D.Triton, Вы писали:

DT>У меня в этом случае вызывается "прямой" insert в таблицу, а потом select SCOPE_IDENTITY()


Тут же все сказано:

Note that the custom sql-insert will not be used if you use identity to generate identifier values for the class.

HgLab: Mercurial Server and Repository Management for Windows
Re[3]: [INFO] NHibernate storedproc params mapping (ord NOT
От: D.Triton Украина  
Дата: 24.06.08 09:46
Оценка:
Здравствуйте, Нахлобуч, Вы писали:

Н>Здравствуйте, D.Triton, Вы писали:


DT>>У меня в этом случае вызывается "прямой" insert в таблицу, а потом select SCOPE_IDENTITY()


Н>Тут же все сказано:


Н>

Н>Note that the custom sql-insert will not be used if you use identity to generate identifier values for the class.


Спасибо, не увидел, но проверил опытным путем.
Я отдельно запостил свою проблему: здесь
Автор: D.Triton
Дата: 24.06.08



Меня интересует, кто и как выставляет первичные ключи, сгенерированные на стороне сервера.
Re: [INFO] NHibernate storedproc params mapping (ord NOT req
От: Polevi  
Дата: 03.07.08 03:47
Оценка:
Здравствуйте, снежок, Вы писали:

С>Параметр, соответствующий id (DocumentID) определяем последним в списке (так требуется для корректной работы NHibernate).


Простите но ваш пример не работает.. SCOPE_IDENTITY() не присваивается полю DocumentId будь оно хоть первое в списке, хть последнее. У вас даже в маппиге указан <generator class="identity" /> — в этом случае <sql-insert> просто игнорируется и SP не вызывается.
Re[2]: [INFO] NHibernate storedproc params mapping (ord NOT
От: снежок Россия  
Дата: 03.07.08 08:24
Оценка:
P>Простите но ваш пример не работает.. SCOPE_IDENTITY() не присваивается полю DocumentId будь оно хоть первое в списке, хть последнее. У вас даже в маппиге указан <generator class="identity" /> — в этом случае <sql-insert> просто игнорируется и SP не вызывается.

Забыл отметить, тестирую на NHibernate 2.0.0 Alpha2.
Может для предыдущих версий действительно есть проблема "Note that the custom sql-insert will not be used if you use identity to generate identifier values for the class.".
У меня работает все на ура.
Re[3]: [INFO] NHibernate storedproc params mapping (ord NOT
От: Polevi  
Дата: 03.07.08 09:02
Оценка:
Здравствуйте, снежок, Вы писали:

P>>Простите но ваш пример не работает.. SCOPE_IDENTITY() не присваивается полю DocumentId будь оно хоть первое в списке, хть последнее. У вас даже в маппиге указан <generator class="identity" /> — в этом случае <sql-insert> просто игнорируется и SP не вызывается.


С>Забыл отметить, тестирую на NHibernate 2.0.0 Alpha2.

С>Может для предыдущих версий действительно есть проблема "Note that the custom sql-insert will not be used if you use identity to generate identifier values for the class.".
С>У меня работает все на ура.

да, на 2.0 работает, подтверждаю
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.