Вызовите выполнение запросов без сброса/фиксации

Привет я использую транзакцию на запрос (сессия в поле зрения) шаблон для веб-приложения asp.net. У меня есть несколько точек в приложении, где я хочу Сохранить управляемый объект NHibernate и затем сделай еще несколько вставок и обновлений с помощью общего sql. Они вставляют/обновляют, зависят от идентификатора, который возьмет сохраненный объект NH.

Проблема состоит в том, что сгенерированный идентификатор не существует в объеме транзакций. Если я вызываю сброс/фиксацию, идентификатор сохраняется, но если вставляет/обновляет сбой, я должен откатывать, но вспыхнувший/зафиксированный объект не будет. В настоящее время я делаю ручную вставку для этих случаев, но это - что-то, что я хочу изменить. Так, есть ли способ выполнить SQL-оператор (в уже открытой транзакции) после Сохранения (), но не вызывая сброс/фиксацию?

Править: Я добавляю пример полупсевдокода, я получил 4 неправильных ответа, таким образом, я думаю, что люди не понимают (как NHibernate работает) В Начать запросе я проблема a

nhsession.BeginTransaction()

затем в какой-то момент я делаю

FooClass fc = new FooClass("value");
nhsession.Save(fc);
ITransaction trans = nhsession.Transaction;
SqlCommand sc = new SqlCommand("some insert/update query that depends on fc's id", (SqlConnection)nhsession.Connection);
sc.Parameters.Add("id", fc.Id); //NHibernate generates the id, note i'm using assigned/hi-lo so no round trip to the db takes place
transaction.Enlist(sc);
try {
    sc.ExecuteNonQuery();
}
catch (SqlException ex){
    transaction.RollBack();
    nhsession.Close();
}

и в конце Запроса я проблема a CommitTransaction() и nhsession.Close()

Теперь это абсолютно ничего не сделает: FooClass (fc) не сбросился/согласился база данных. Save() операция, которую сделал NH, до той точки, в оперативной памяти. Это означает, что никакая команда sql не была дана nhibernate, и это означает что SqlCommand (sc) то, что я стреляю, впоследствии потерпит полный провал, поскольку идентификатор не существует.

Если я делаю сброс/фиксацию между Save() и SqlCommand FooClass(fc) _cannot_be_rolled_back_ и это являются плохой плохой вещью. В настоящее время, чтобы это работало, я делаю ваниль sql, вставляют использование SqlCommand, и я хочу изменить это. (Почему? потому что я не хочу делать ваниль, вставляет, они восприимчивы к ошибкам из-за изменений схемы/модели, и я получил OR/M для этого),

Как? я хочу уведомить NHibernate так или иначе для выполнения SqlCommand к соответствует Save() вставьте (черт, это может сделать весь SqlCommands, который это собрало), но без него фиксирование или сбрасывание!.

В настоящее время я также ищу подготовленный sql оператор, который производит nhibernate, когда сбрасывать/фиксировать сохраненный объект. Возможно, я могу просто взять ту строку и выполнить ее в моем SqlCommand, который включается в список в Транзакцию.

6
задан Jaguar 18 February 2010 в 21:59
поделиться

5 ответов

может я не понимаю, но вы не можете так сделать ...

using(var tx = session.BeginTransaction())
{
    session.Save(entity);
    session.Flush();

    //perform non NH operations with entity.id

    tx.Commit();
}//uncommitted transaction would be rolled back on dispose()
5
ответ дан 17 December 2019 в 02:27
поделиться

Похоже, вам нужен уровень изоляции «грязного чтения» во время транзакции. Это позволит вам читать «незарегистрированный», но «сохраненный» контент. Однако я недостаточно хорошо владею NHibernate, чтобы дать какое-либо представление о том, как это сделать там.

Я уверен, что кто-то еще может понять, как сделать уровень изоляции «грязного чтения» для NH.

0
ответ дан 17 December 2019 в 02:27
поделиться

Я использую Castle ActiveRecord поверх NHibernate, но принцип должен быть таким же, мой DTC отключен, поэтому я не уверен, что это работает, но это должно быть правильное направление.

Imports Castle.ActiveRecord
imports NHibernate.Expression

<ActiveRecord> _
Public Class Test1
    Inherits ActiveRecordBase(Of Test1)

    Private _id As Guid
    <PrimaryKeyAttribute(PrimaryKeyType.Guid)> _
    Public overridable Property Id as Guid
        Get
            return _id
        End Get

        Set(value As guid)
            _id = value
        End Set
    End Property


    Private _prop1 As String
    <[Property]> _
    Public overridable Property prop1 as String
        Get
            return _prop1
        End Get

        Set(value As String)
            _prop1 = value
        End Set
    End Property

End Class

<ActiveRecord> _
Public Class Test2
    Inherits ActiveRecordBase(Of Test2)

    Private _id As Guid
    <PrimaryKey(PrimaryKeyType.Guid)> _
    Public overridable Property Id as Guid
        Get
            return _id
        End Get

        Set(value As guid)
            _id = value
        End Set
    End Property

    Private _prop1 As String
    <[Property]> _
    Public overridable Property prop1 as String
        Get
            return _prop1
        End Get

        Set(value As String)
            _prop1 = value
        End Set
    End Property

    Private _t1 As Test1
    <BelongsTo()> _
    Public overridable Property t1 as Test1
        Get
            return _t1
        End Get

        Set(value As test1)
            _t1 = value
        End Set
    End Property


End Class

Imports Castle.ActiveRecord
Imports NHibernate.Expression
Imports System.Data.SqlClient
Imports System.Transactions
imports System.Configuration

Public Module Module1
    Public Class modMain
        Public Shared Sub Main()
            Castle.ActiveRecord.ActiveRecordStarter.Initialize()
            Using T As New System.Transactions.TransactionScope(ondispose.Rollback)
            Dim x As New Test1()
            x.prop1 = "Hello"
            x.Save

            using c As New SqlConnection()
                c.ConnectionString = ConfigurationManager.ConnectionStrings("Development").ConnectionString
                Dim cmd As SqlCommand = c.CreateCommand()
                cmd.CommandText = "insert into test2(prop1, t1) values(@prop1, @t1)"
                Dim p As SqlParameter = cmd.CreateParameter()
                p.Direction = parameterdirection.Input
                p.DbType = dbtype.Guid
                p.ParameterName = "@prop1"
                p.Value = "Test"

                cmd.Parameters.Add(p)
                p = cmd.CreateParameter()
                p.Direction = parameterdirection.Input
                p.DbType = dbtype.Guid
                p.ParameterName = "@t1"
                p.Value = x.Id

                c.Open
                cmd.ExecuteNonQuery
            end using

            t.Complete
            end using

        End Sub
    End Class
End Module
0
ответ дан 17 December 2019 в 02:27
поделиться

Пробовали ли вы использовать прямые возможности NHibernate по работе с SQL? Вместо разбиения на SQLCommand, о котором NHibernate ничего не знает, вы можете использовать ISession.CreateSQLQuery("native SQL here"). Если вы затем сделаете это внутри транзакции после метода Save, NHibernate выполнит все операторы по порядку, когда произойдет Commit. Таким образом:

using(var tx = session.BeginTransaction())
{
    try
    {
        FooClass fc = new FooClass("value");
        nhsession.Save(fc);

        var nativeQuery = nhsession.CreateSQLQuery("some insert/update query that depends on fc's id");

        // Add parameters to nativeQuery using SetXXX methods
        nativeQuery.SetXXX(...);

        // Save nativeQuery
        nativeQuery.Save(); // I think...

        tx.Commit();
    }
    catch (...)
    {
        tx.Rollback();
    }
}

Смотрите здесь еще один похожий вопрос относительно использования родного запроса NH: Hibernate NHibernate - Native SQL

0
ответ дан 17 December 2019 в 02:27
поделиться

Разве вы не можете использовать вложенные транзакции или области транзакций для поддержки этого?

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

Как выполнять вложенные транзакции в NHibernate? В есть образец кода, демонстрирующий подход с использованием областей видимости.

1
ответ дан 17 December 2019 в 02:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: