nHibernate TooManyRowsActedException Неожиданный счетчик строк: X;ожидается: 1 - PullRequest
0 голосов
/ 25 февраля 2019

Я использую nHibernate с Sybase и получаю TooManyRowsActedException" Неожиданный счетчик строк: 5; ожидается: 1 " при сохранении в таблицу, причина этого в том, чтоиз-за срабатывания триггеров в базе данных.

  • У меня есть базовый класс клиента (ClientId, ClientType, LanguageCode), который должен быть сохранен в таблице CLIENT
  • У меня есть класс Person (Фамилия, Имя, Название), который должен бытьсохранено в таблице PERSON
  • У меня есть класс Organization (OrgName, RegNo), который следует сохранить в таблице OERGANISATION
  • И PERSON, и ORGANIZATION наследуются от CLIENT. Когда я сохраняю Person, nHibernate сначала сохраняет в CLIENT, а затем пытается сохранить в PERSON.

К сожалению, мне не разрешено изменять триггеры (т.е.добавьте "set NOCOUNT ON" - как здесь: NHibernate TooManyRowsActedException )

Вместо этого мне нужно получить nHibernate, чтобы пропустить количество строк.Для этого я попытался: TooManyRowsActedException с зашифрованными триггерами , но безуспешно:

Инжектированный измененный NonBatchingBatcherWithoutVerification AddToBatch выполняется, когда я вызываю .Commit(), но все еще выбрасывает строкуподсчет исключений.

До того, как я написал свой собственный «NonBatchingBatcherWithoutVerification» (см. ниже), я получил ошибку триггера при вставке в CLIENT (первая таблица), НО после написания своего собственного введенного класса (без повышения числа строк)получить запрос количества строк на вставке PERSON (2-я вставка, а не 1-я вставка CLIENT)

Мой код выглядит следующим образом:

Настройка конфигурации nHibernate (с введеннымNonVerifyingBatcherFactory : IBatcherFactory) и сохранить в базе данных:

  var cfg = new Configuration();
  cfg.DataBaseIntegration(x =>
  {
      x.ConnectionString ="Data Source='';Database=;Port='';UID='';PWD=''";
      x.Dialect<SybaseASE15Dialect>();
      x.LogSqlInConsole = true;
      x.BatchSize = 1;
      x.Driver<DriverWithCustomBatcherFactory>(); });

  cfg.DataBaseIntegration(db => db.Batcher<NonVerifyingBatcherFactory>());

  cfg.Configure();

  var sesFact = cfg.BuildSessionFactory();

  using (var session = sesFact.OpenSession()) {

      using (var tx = session.BeginTransaction()){

      Person newPerson = new Person();
      newPerson.Title = "Mr";
      newPerson.Forenames = "THOMAS";
      newPerson.Surname = "BYRNE";
      newPerson.ClientType = "P";
      newPerson.LanguageCode = "ENG";
      newPerson.NationalityCode = "GBR";
      newPerson.NormalCountryOfResidence = "GBR";

      var nextClientId = session.QueryOver<Client>()
      .Select(Projections.Max<Client>(c => c.ClientId))
      .SingleOrDefault<int>() + 1;

      session.Save(newPerson);
  tx.Commit();
  }

Новый внедренный класс NonVerifyingBatcherFactory, реализующий IBatcherFactory

public class NonVerifyingBatcherFactory : IBatcherFactory
{

    public virtual IBatcher CreateBatcher(ConnectionManager connectionManager, IInterceptor interceptor)
    {
        return new NonBatchingBatcherWithoutVerification(connectionManager, interceptor);

    }
}

Я пытался реализовать AddToBatch и DoExecuteBatch- оба без VerifyOutcomeNonBatched

public class NonBatchingBatcherWithoutVerification : NonBatchingBatcher
{

    public NonBatchingBatcherWithoutVerification(ConnectionManager connectionManager, IInterceptor interceptor)
        : base(connectionManager, interceptor)
    {
        //BatchSize = 1;
    }

    public override void AddToBatch(IExpectation expectation)
    {
            IDbCommand cmd = CurrentCommand;
            ExecuteNonQuery(cmd);
            // Removed the following line
            //expectation.VerifyOutcomeNonBatched(rowCount, cmd);

    }

    protected override void DoExecuteBatch(System.Data.IDbCommand ps)
    {
        //IDbCommand cmd = CurrentCommand;
        //ExecuteNonQuery(ps);
    }
}



public class DriverWithCustomBatcherFactory : SybaseAseClientDriver, IEmbeddedBatcherFactoryProvider
{
    public Type BatcherFactoryClass
    {
        get { return typeof(NonVerifyingBatcherFactory); }
    }
}
  • Причина в том, что я не использую nHibernate Fluent:
  • Или не настроен Пакетная обработка правильно - но нет x.AdoNetBatchSize only x.BatchSize:

    cfg.DataBaseIntegration(
        x =>
        {
            x.ConnectionString ="Data Source='';Database=;Port='';UID='';PWD=''";
            x.Dialect<SybaseASE15Dialect>();
            x.LogSqlInConsole = true;
    

В файле hibernate.cfg.xm также можно выполнить следующие действия:

<property name="adonet.factory_class">NHibernateTest.NonVerifyingBatcherFactory, NHibernateTest</property>
<property name="adonet.batch_size">100</property>

Отображения CLIENT и PERSON настраиваются следующим образом:

<id name="ClientId" column="CLIENT_ID"  type = "int">
  <generator class="assigned"/>
</id>

<property name="LanguageCode" column="LANGUAGE_CODE" type = "string"/>
<property name="ClientType" column="CLIENT_TYPE" type = "string"/>

<joined-subclass name="Person" table="PERSON">
  <key column="CLIENT_ID" />
  <property name="Surname" column="SURNAME"/>
</joined-subclass>

<id name = "ID">
  <generator class = "native"/>
</id>

<property name = "CLIENT_ID"/>
<property name = "SURNAME"/>
<property name = "FORENAMES"/>


RECAP При сохранении в PERSONтаблица, запись CLIENT сначала сохраняется в таблице CLINE - (наследуется и в файле .hbm.xml)

Если adonet.factory_class & adonet.batch_size не присутствует в конфигурации, я получаю: TooManyRowsActedException" Неожиданное количество строк: ** 5; Ожидается: 1 **" << - из триггера КЛИЕНТА я думаю </p>

, если adonet.factory_class & adonet.batch_size присутствуют в конфигурации. Я получаю: TooManyRowsActedException" Неожиданное количество строк: ** 32; Ожидается: 1 **" << - от ЧЕЛОВЕКАтриггер я думаю </p>

Любая помощь будет принята с благодарностью, спасибо!

...