| 
			
			 | 
		#461 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 Цитата: 
	
Если использовали GUID - опять же, могу ошибаться, но тут скорее всего пришли люди которые с системой до этого не работали(не знают что такое номерные серии), и начали проектировать данные таблицы. Можно конечно предположить, ну ладно, системы не знают, но наверное технически специалисты хорошие. Но в этом заставляет сомневаться вот такие графики в презентации (нет подписей для оси Х и У, непонятно что вообще проверяли) Плюс я немного работал над оптимизаций складов, и я никогда не видел в топе нагрузки запросы связанные именно с InventTrans, а те что были, они бы к примеру выиграли от денормализации InventTrans, добавления к примеру туда всех полей аналитик(но тут явно обратный процесс) Что они запроектируют - даже страшно представить, но будем надеяться на лучшее  | 
| 
	
 | 
| 
			
			 | 
		#462 | 
| 
			
			 Участник 
		
			
	 | 
	
	|
| 
	
 | 
|
| За это сообщение автора поблагодарили: gl00mie (2). | |
| 
			
			 | 
		#463 | 
| 
			
			 Участник 
		
			
	 | 
	
	|
| 
	
 | 
|
| За это сообщение автора поблагодарили: axm2017 (12). | |
| 
			
			 | 
		#464 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 Цитата: 
	
\Data Dictionary\Tables\EventInbox\Methods\nextEventId или свой системный счетчик 64-битных идентификаторов сделать один раз по аналогии. И вести его в разрезе TableId.  | 
| 
	
 | 
|
| За это сообщение автора поблагодарили: fed (5). | |
| 
			
			 | 
		#465 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 X++: public void delete() { super(); element.updateWorkflowButtonEnabled(); element.updateWorkflowButtonForLineVisibility(); element.close(); }  | 
| 
	
 | 
| 
			
			 | 
		#466 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 Цитата: 
	
Метод delete() на датасорсе PurchReqTable, верно? Посмотрел на R3, присутствует только вызов close(). 
				__________________ 
		
		
		
		
		
			// no comments Последний раз редактировалось dech; 31.03.2023 в 14:52.  | 
| 
	
 | 
| 
			
			 | 
		#467 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			На 365
		 
		
		
		
		
		
		
		
	 | 
| 
	
 | 
| 
			
			 | 
		#468 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			В классе Global метод con2Str 
		
		
		
		
		
		
		
	В стандарте, если в контейнере значения первых позиций будут пустыми строками, то метод их проигнорирует и не добавит после них разделитель. Из-за этого количество элементов в контейнере и в результирующей строке будет разным. Может быть в этом и была какая-то логика, если бы это работало со всеми пустыми элементами. Но вот "пустые" значения идущие после первого "не пустого" элемента контейнера уже будут обрамлены разделителем. Я считаю что это явно ошибка и в строке должны быть представлены все элементы контейнера и пустые и не пустые. Причина ошибки и собственно исправление: X++: static str 1000 con2Str(container c, str 10 sep = ',') { int idx = 0; int len = conlen(c); str 100 tmp; str 1000 retStr; ; while (idx < len) { idx += 1; // KSM fix empty string -->> // if (retStr) if (idx > 1) // KSM fix empty string <<-- retStr += sep; tmp = conpeek(c,idx); retStr += tmp; } return retStr; } Здесь интересен ещё один момент. Как значения типа anytype преобразуется в строку? По каким правилам происходит такое преобразование? Например дата: X++: static void TestAnytype2StrConvert(Args _args) { date t = today(); anyType a = t; str 100 s = a; ; info(s); }  | 
| 
	
 | 
|
| За это сообщение автора поблагодарили: Logger (1). | |
| 
			
			 | 
		#469 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			В AnyType также присутствует дополнительная информация о базовом типе. В зависимости от этого типа используется уже конкретное преобразование. В strFmt() также используется anytype в качестве аргументов (кроме первого, который должен быть строкой). strFmt корректно преобразует любой переданный аргумент в строку, будь то число, енум или дата.
		 
		
		
		
		
		
		
			
				__________________ 
		
		
		
		
	// no comments  | 
| 
	
 | 
| 
			
			 | 
		#470 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			P.S. Я думаю, во всех таких случаях используется функция any2str().
		 
		
		
		
		
		
		
			
				__________________ 
		
		
		
		
	// no comments  | 
| 
	
 | 
| 
			
			 | 
		#471 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			Там все немного заморочнее 
		
		
		
		
		
		
		
		
			X++: static void Job287(Args _args) { str sDate; anytype aDate = 11\12\2023; str sReal; anytype aReal = 1024.5678; ; sDate = aDate; sReal = aReal; info(strFmt("sAdate = %1", sDate)); info(strFmt("aDate = %1", aDate)); info(strFmt("sReal = %1", sReal)); info(strFmt("aReal = %1", aReal)); // info(strFmt("any2str(aDate) = %1", any2str(aDate))); // ошибка // info(strFmt("any2str(aReal) = %1", any2str(aReal))); // ошибка } Цитата: 
	
		
			sAdate = 2023.12.11 
aDate = 11.12.2023 sReal = 1024.5678 aReal = 1 024,57 А any2str - никакого реального преобразования не делает. Эта функция - что-то типа Debug::assert() - только она проверяет что реально передана переменная строкового типа иначе выбрасывает исключение. Ну и конечно подсказывает компилятору какой имелся в виду тип, подавляя тем самым предупреждения компилятора. Поэтому для реального преобразования в строку мы писали свою функцию. strFmt не всегда подходит из-за строгого округления до 2 знаков после запятой для вещественных чисел. Последний раз редактировалось Logger; 28.04.2023 в 07:58.  | 
| 
	
 | 
|
| За это сообщение автора поблагодарили: S.Kuskov (5). | |
| 
			
			 | 
		#472 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 Цитата: 
	
![]() У меня целая иерархия классов-атрибутов. По классу почти для каждого базового типа. В нужном месте [классатрибутСпараметрами] и его взрослая обработка.  | 
| 
	
 | 
|
| За это сообщение автора поблагодарили: Logger (1). | |
| 
			
			 | 
		#473 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			Разбирался тут с "тяжелыми" запросами и в том числе обнаружил там такое: 
		
		
		
		
		
		
		
	PHP код: 
	
			
	 | 
| 
	
 | 
| 
			
			 | 
		#474 | 
| 
			
			 Moderator 
		
			
	 | 
	
	
	
		
		
		
		 Цитата: 
	
		
			Сообщение от gl00mie
			 
 
			Казалось бы, что с ним не так? А то, что он не использует параметры и плодит, собака, сотни одинаковых планов запроса, которые вымывают из кэша другие более полезные планы запросов. С помощью "триангуляции" обнаружил, что такие запросы генерятся (в DAX2012 R3) из AccountingEventSourceDocumentProcessor::updateDistributionsForEvent(). Спрашивается, что мешало смастерить там прямой SQL-запрос с параметрами, чтобы он не плодил кучу одинаковых планов запросов?.. 
		
	 | 
| 
	
 | 
| 
			
			 | 
		#475 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 Цитата: 
	
X++: AccountingEventSourceDocumentProcessor::executeSQL(sqlStatementText); Еще и комментарий написан X++: // Do the update as direct SQL as there is a deadlock on AccountingDistribution due to a clustered // index scan operator in the query plan. This operator appears only in low data volume scenarios. // In higher volume scenarios, the plan includes a seek operator using the index I_7452SOURCEDOCUMENTHEADERIDX. // Testing in SSMS indicates an index hint will correct the plan at low volumes and represents minimal // risk at high volumes. In order to enable the index hint on the update_recordset, direct SQL must be used. // Also note that xGlobal::randomPositiveInt32() is the method used by the kernel to populate the // recversion field. 
				__________________ 
		
		
		
		
	- Может, я как-то неправильно живу?! - Отчего же? Правильно. Только зря...  | 
| 
	
 | 
| 
			
			 | 
		#476 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 Цитата: 
	
Т.е. на момент написания кода вполне могло быть, что добавление DECLARE все-равно приводило к созданию нового плана запроса 
				__________________ 
		
		
		
		
	- Может, я как-то неправильно живу?! - Отчего же? Правильно. Только зря...  | 
| 
	
 | 
| 
			
			 | 
		#477 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 Цитата: 
	
X++: private static server boolean updateDistributionsForEvent(recId _accountingEventRecId, AccountingDate _accountingDate, recId _sourceDocumentRecId) { str sqlStatementText; str sqlDate = date2str(_accountingDate, 321, 2, 3, 2, 3, 4, DateFlags::None); // 'YYYY-MM-DD' // Do the update as direct SQL as there is a deadlock on AccountingDistribution due to a clustered // index scan operator in the query plan. This operator appears only in low data volume scenarios. // In higher volume scenarios, the plan includes a seek operator using the index I_7452SOURCEDOCUMENTHEADERIDX. // Testing in SSMS indicates an index hint will correct the plan at low volumes and represents minimal // risk at high volumes. In order to enable the index hint on the update_recordset, direct SQL must be used. // Also note that xGlobal::randomPositiveInt32() is the method used by the kernel to populate the // recversion field. sqlStatementText = strFmt('UPDATE T1 SET ACCOUNTINGEVENT=%1,RECVERSION=%2 FROM ACCOUNTINGDISTRIBUTION T1 WITH (INDEX(I_7452SOURCEDOCUMENTHEADERIDX)) CROSS JOIN SOURCEDOCUMENTLINE T2 ', _accountingEventRecId, xGlobal::randomPositiveInt32()); sqlStatementText += strFmt('WHERE (((T1.PARTITION=%1) AND (T1.ACCOUNTINGEVENT=0) AND (T1.ACCOUNTINGDATE={ d\'%2\'})) AND (T1.SOURCEDOCUMENTHEADER=%3)) AND ', getcurrentpartitionrecid(), sqlDate, _sourceDocumentRecId); sqlStatementText += strFmt('((T2.RECID=T1.SOURCEDOCUMENTLINE) AND (T2.ACCOUNTINGSTATUS=%1 OR T2.ACCOUNTINGSTATUS=%2)) AND (T2.PARTITION=%3)', enum2int(SourceDocumentLineAccountingStatus::Completed), enum2int(SourceDocumentLineAccountingStatus::Canceled), getcurrentpartitionrecid()); return AccountingEventSourceDocumentProcessor::executeSQL(sqlStatementText); }  | 
| 
	
 | 
| 
			
			 | 
		#478 | 
| 
			
			 Участник 
		
			
	 | 
	
	|
| 
	
 | 
| 
			
			 | 
		#479 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 Цитата: 
	
https://habr.com/ru/articles/658855/ Комменты, как обычно, еще интереснее.  | 
| 
	
 | 
|
| За это сообщение автора поблагодарили: S.Kuskov (2). | |
| 
			
			 | 
		#480 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			Не сдержусь и в который раз пошлю лучи всего плохого авторам метода CompanyInfo::find() 
		
		
		
		
		
		
		
	X++: public static CompanyInfo find(boolean _forupdate = false, RecId _recId = 0, boolean _initializePartyNumberSeq = false, boolean useGuid = false) X++: int64 refRecId;
CompanyInfo::find(refRecId); | 
| 
	
 |