Я использую 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>
Любая помощь будет принята с благодарностью, спасибо!