26.09.2008, 13:17 | #1 |
Мрачный тип
|
Потеря активного буфера записи при вызове super() в update() таблицы
3.0 SP3
На одном из подопечных проектов(весьма запущенный проект, к слову сказать - сброс RecId был уже и в таблице RContractTable есть с десяток дублей RecId, в таблице отключено св-во CreateRecIdIndex.) при сохранении изменений в форме договоров и, соответсвенно, при исполнении метода super() в переопределенном update() (перед super() - только сохрание буфера записи c this.orig() ) у RContractTable вылетает ошибка "Невозможно отредактировать запись в 'Договоры' ('RContractTable'). Запись удалена другим пользователем." RecId данного договора в списке дублирующихся нет ... На некоторых договорах все ОК, на именно этом - такой вот затык SQL, генеримый системой X++: SQL: SELECT A.RCONTRACTPARTNERTYPE,A.RCONTRACTACCOUNT,A.RCONTRACTNUMBER,A.CONTRACTDATE,A.CONTRACTSTARTDATE, A.CONTRACTENDDATE,A.CONTRACTAMOUNT,A.CONTRACTVATAMOUNT,A.CURRENCYCODE,A.CONTRACTPAYMCODE,A.RCONTRACTPARTNERCODE, A.RCONTRACTSTATUS,A.CONTRACTPOSTINGPROGILE,A.CONTRACTPREPAYMENTPOSTING16014,A.CONTRACTRESPONSIBLEPERSON, A.CONTACTPERSONID,A.CONTRACTPAYMMODE,A.CONTRACTPAYMSPEC,A.CONTRACTPAYMENTSCHED,A.CONTRACTCASHDISC,A.CONTACTPHONE, A.LINEOFBUSSENESID,A.CONTACTTELEX,A.CONTACTURL,A.CONTACTEMAIL,A.CONTACTTELEFAX,A.CONTACTCELLULARPHONE,A.CONTACTPHONELOCAL, A.CONTRACRTHRMORGANISATIONID,A.RCONTRACTCODE,A.RCONTRACTPAYMDAYID,A.VGP_RCONTRACTSUBJECTID,A.VGP_RCONTRACTCITYNAME, A.VGP_RDATEVISALIST,A.VGP_RCONTRACTFOLDERID,A.VGP_RCLOSECAUSE,A.VGP_DIMENSION,A.VGP_DIMENSION2_,A.VGP_DIMENSION3_, A.VGP_DIMENSION4_,A.VGP_DIMENSION5_,A.VGP_DIMENSION6_,A.VGP_DIMENSION7_,A.VGP_DIMENSION8_,A.VGP_DIMENSION9_,A.VGP_DIMENSION10_, A.VGP_DIMENSION11_,A.VGP_DIMENSION12_,A.VGP_ISCREDITCONTRACT,A.VGP_PENALTY,A.VGP_SURCHARGE,A.VGP_PERCENT, A.VGP_RCONTRACTPARTNERNAME,A.VGP_CONTRACTRESPONSIBLEPE50014,A.VGP_CONTRACTRESPONSIBLEOR50015,A.VGP_ADDITIONALPAYMENTINFO, A.VGP_FIXEDPERCENT,A.VGP_SETTLEMENTID_RU,A.VGP_SETTLEMENTNAME,A.VGP_CITYID,A.VGP_COUNTYID,A.VGP_STATEID,A.VGP_TOMSKREGION, A.VGP_DEBETORNAME,A.VGP_DEBETORCODE,A.VGP_CREDITPURPOSE,A.VGP_TRANSACTIONDEBTS,A.VGP_BAILS,A.VGP_DEPOSIT,A.VGP_CREDITPERIOD, A.VGP_PAYMENTDATE,A.VGP_COMMENTS,A.FORPRINT,A.VGP_RCONTRACTGROUP,A.VGP_RCONTRACTTYPEID,A.VGP_PLACEOFREGISTRATIONID, A.VGP_REGISTRATIONGOVERNMENTID,A.VGP_EAREGISTRATIONDATE,A.VGP_EAREGISTRATIONNUM,A.VGP_EACANREGISTRATION, A.VGP_EAPROJECTCREATEDATE,A.VGP_EARCONTRACTACCOUNT,A.VGP_EACONTRACTPLANENDDATE,A.VGP_POWEROFATTORNEYOWNID, A.VGP_POWEROFATTORNEYOUTID,A.VGP_EADECISION,A.VGP_DECISIONTRANSDATE,A.VGP_EAAUTHORITYID,A.VGP_EARENTER, A.VGP_EAOWNER,A.VGP_EAORDER,A.VGP_EAORDERTRANSDATE,A.VGP_EABENEFIT,A.VGP_EAPREMIUM,A.VGP_EACURRENCYPREMIUM, A.VGP_EAREPORT,A.VGP_EAREPORTTRANSDATE,A.VGP_EAREPORTTRANSDATEEND,A.VGP_EAREGISTRATIONDATEHYP50063, A.VGP_EACONTRACTAMOUNTMTH,A.VGP_EARENTPAYMENTYEAR,A.VGP_EAFACTOROTHERCHARGE,A.VGP_EAPLANRESIDUALVALUEDATE, A.VGP_EAFRANCHISE,A.VGP_EAPAWNRCONTRACTACCOUNT,A.VGP_EAHYPOTHECRCONTRACTACCOUNT,A.TGP_CREDITTYPE, A.TGP_PARTNERTYPE,A.TGP_CUSTVENDPOSTINGPROFILE,A.TGP_RESTCREDITCONTRACT,A.LEDGERJOURNALNUM, A.VGP_EACREDITPERCENT,A.VGP_VATPERCENT,A.LEASINGAMOUNT,A.MODIFIEDDATE,A.MODIFIEDTIME,A.RECID, A.RCONTRACTSUBJECT,A.VGP_RCONTRACTCOMMENT,A.VGP_EACONTRACTNOTES FROM RCONTRACTTABLE A(INDEX(I_16375CONTRACTTYPECODEAC16001) UPDLOCK) WHERE ((DATAAREAID=?) AND ((RCONTRACTACCOUNT=?) AND ((RCONTRACTCODE=?) AND (RCONTRACTPARTNERTYPE=?)))) OPTION(FAST 1) [=35, =] Или уже это трындец и он неизлечим ?
__________________
Мы летаем, кружимся, нагоняем ужасы ... Последний раз редактировалось TasmanianDevil; 26.09.2008 в 13:37. |
|
26.09.2008, 15:07 | #2 |
Сенбернар
|
Может, глупость скажу... А индексы на RContractTable не пробовали перестроить?
__________________
Best Regards, Roman |
|
30.09.2008, 10:06 | #3 |
Мрачный тип
|
RVS, серверные сервы клянутся и божатся, что по Maintance Plan все включено и чуть ли не еженедельно ребилдится и шринкуется, и логами успешными в лицо тычат. Единственный оставшийся уникальный индекс по компании/типу партнера/группе/коду (второй индекс по RecId отключен по вышеописанным причинам) жив-здоров (Query Analyzer при исполнении запроса в Execution Plan показывает Clustered Index Seek). Однако явление имеет место быть ...
ExecuteQuery()/Init() у датасорса на форме никто не ломал, все поля выбираются и ядру для формирования запроса они доступны. В обозревателе таблицы та же картина ... Код в update() таблицы до super() прост и пакостить не может ... X++: public void update() { RContractTable old = this.orig(); CustAccount accountOld = old.RContractPartnerCode; super(); ... } Мозг уже в разрыве и стекает по стенкам черепа
__________________
Мы летаем, кружимся, нагоняем ужасы ... |
|
30.09.2008, 11:00 | #4 |
Ищущий знания...
|
не знаю конечно, проблема странная но может не хватает точки с запятой в коде, и аха что то не понимает:
X++: public void update() { RContractTable old = this.orig(); CustAccount accountOld = old.RContractPartnerCode; ; // вот эта точка с запятой super(); ... }
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с) С Уважением, Елизаров Артем |
|
30.09.2008, 14:05 | #5 |
Мрачный тип
|
lev, она б в момент компиляции на это ругнулась (с какой-нибудь ошибкой не к месту, но ругнулась бы). Это ж атавизм старых версий, когда четко необходимо было отделять объявление переменных и локальных функций внутри функции точкой с запятой.
P.S. На всякий случай проверил - никаких изменений ...
__________________
Мы летаем, кружимся, нагоняем ужасы ... |
|
30.09.2008, 14:09 | #6 |
Ищущий знания...
|
Такой вопрос назрел, а до вызова супер есть курсор RContractTable ?
Может перекрыть метод на таблице и посмотреть что происходит в нем?
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с) С Уважением, Елизаров Артем |
|
30.09.2008, 14:11 | #7 |
Ищущий знания...
|
Да ещё, а не сравнивали договор на котором ругается с тем,который нормально сохраняется (по полям).
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с) С Уважением, Елизаров Артем |
|
30.09.2008, 14:58 | #8 |
Мрачный тип
|
lev, super() не перекроешь - это же вызов родительского метода, update() у класса xRecord - отттуда эта ошибка валится. Дебаггер тоже туда не проникает.
А каков смысл сравнения по полям ? Они разные Поля, входящие в уникальный индекс, по которому идет позиционирование на сервере для последующего изменения найденной записи, до момента вызова super() имеют определенные значения, трассируемый запрос с этими значениями отрабатывается Query Analyzer'ом и планом исполнения подтверждается корректность имеющегося индекса, по которому идет выборка. Какой из этого вывод ? Где-то внутри super() эти значения теряются и к серверу, при изменении на этой записи, формируется "левый" запрос, не возвращающий искомую запись ? Но от подобных выводов становится как-то страшно жить ...
__________________
Мы летаем, кружимся, нагоняем ужасы ... |
|
30.09.2008, 15:43 | #9 |
Злыдни
|
А "отсечь" форму пробовали? Например, открыть запись в обозревателе, поменять поле какое-нибудь и сохранить. Тоже пошлет? RLS есть? Лог базы данных на таблице есть? Под админскими правами ошибка воспроизводится?
|
|
30.09.2008, 16:06 | #10 |
Пенсионер
|
Может где-то до вызова этого метода, по какому-нибудь условию, происходит передача "this" куда-нибудь. Например в modifiedField.
__________________
Законы природы еще никто не отменял! А еще у меня растет 2 внучки!!! Кому интересно подробности тут: http://www.baby-shine.com/ |
|
01.10.2008, 06:55 | #11 |
Мрачный тип
|
Yprit, в браузере таблиц та же картина ..
Права админские, RLS не используем на этой табле, лог есть и нормально отрабатывает (оба буфера, оригинал и измененный, там проходят в полном составе). blokva, нет там такого, но даже если бы и было - все равно в конце концов будет отрабатываться write() датасорса (с буфером записи все ОК), из него update() на таблице (там до super() все ОК), а из него update() на xRecord, в котором пишется лог(там тоже все ОК с буфером) - а вот дальше, в недоступном для трассировке месте что-то случается... Трассировка SQL, к сожалению, не показывает конкретные величины значений на ключевые поля и тут приходится только подозревать, что именно эта запись как-то сносит крышу системным классам ...
__________________
Мы летаем, кружимся, нагоняем ужасы ... |
|
01.10.2008, 08:51 | #12 |
Злыдни
|
Мда... Кэширование какое на таблице? Если сбросить кэш и попробовать проапдейтить - все равно ругнется?
|
|
01.10.2008, 10:10 | #13 |
Участник
|
Воспользуйтесь профайлером из состава сиквела.
Там видны значения, передаваемые в запрос. Или попробуйте включить литералы - перекройте ExecuteQuery() на датасорсе и перед super() вставьте X++: this.query().literals(1);
super();
__________________
Axapta v.3.0 sp5 kr2 |
|
|
За это сообщение автора поблагодарили: TasmanianDevil (3). |
01.10.2008, 11:36 | #14 |
Мрачный тип
|
AndyD, спасибо !!!
Нашли, где собака порылась ! RContractAccount, наследуемый от RContractAccountActive, имеет выравнивание вправо. В базе поле RContractAccount "_ _ _ _506/06", трассировка SQL дает совершенно другое значение кол-ва пробелов - "_ _ _ _ _ _ _ _ _506/06". С полтора года назад уже вычисленный джентельмен изменил размер этого поля в сторону увеличения. Счас будем его беседовать ... P.S. Выравнивание вправо - зло.
__________________
Мы летаем, кружимся, нагоняем ужасы ... Последний раз редактировалось TasmanianDevil; 01.10.2008 в 11:56. |
|