Вопрос

В чем разница между

new Guid("00000000-0000-0000-0000-000000000000")

new Guid("10000000-0000-0000-0000-000000000000")

и Guid.Empty?

Нравится

2 комментария
Лучший ответ

1 и 2 - разные значения Guid.

Guid.Empty - это статичная константа, в которой лежит Guid = "00000000-0000-0000-0000-000000000000".

Нулевым Guid символизируется отсутствие значения, так как в C# тип Guid - это структура, следовательно не может принимать null.

При считывании из БД справочного значения null в переменную будет присваиваться "00000000-0000-0000-0000-000000000000". Для БД нулевой Guid является валидным значением, и если попробуете присвоить его в справочное поле, то БД выдаст ошибку ограничения внешнего ключа (в ссылаемой таблице нет значения с Id состоящим из нулей). Как раз для этих случаев переменные сравнивают с константой Guid.Empty, чтобы случайно не установить такое значение и не поломать процесс ошибкой.

1 и 2 - разные значения Guid.

Guid.Empty - это статичная константа, в которой лежит Guid = "00000000-0000-0000-0000-000000000000".

Нулевым Guid символизируется отсутствие значения, так как в C# тип Guid - это структура, следовательно не может принимать null.

При считывании из БД справочного значения null в переменную будет присваиваться "00000000-0000-0000-0000-000000000000". Для БД нулевой Guid является валидным значением, и если попробуете присвоить его в справочное поле, то БД выдаст ошибку ограничения внешнего ключа (в ссылаемой таблице нет значения с Id состоящим из нулей). Как раз для этих случаев переменные сравнивают с константой Guid.Empty, чтобы случайно не установить такое значение и не поломать процесс ошибкой.

Egor Vladimirsky,

Добрый день Егор, подскажите какая у вас проблема?

Показать все комментарии

При создании сценария через JMeter создаются обращения и переводятся в работу. Необходимо чтобы и наряды переходили в статусы дальше, но через штатные решения jmetr'а решения не было найдено. Пришла идея что возможно нужно что-то отключить в системе, потому что отправляя запросы со сгенерированными через jmeter guid для нарядов система заменяет на автоматически созданные. У кого какие есть идеи? Возможно ли отключить проверку и ставить свои значения?

Нравится

2 комментария

Можете написать свой сервис и в методе этого сервиса менять статус обращения и сохранять обращение без валидации полей.

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

В Вашем случае нужно другое, выяснить, почему Вы заполняете Id, а он не передаётся. При обычной работе из раздела, создании новой записи, её Guid формируется на клиенте и передаётся на веб-сервис, где и присваивается новой записи, как я уже писал.

Нужно смотреть, какие запросы к DataService или другим стандартным сервисам Вы отправили. Например, в Fiddler или встроенными средствами браузера.

Показать все комментарии

Добрый день возникла ошибка,когда пытаюсь зайти в мастер раздела, я пробовал найти этот элемент в таблице записей, а также через uid колонок, но там пусто не совсем знаю куда рыть(полную генерацию, компиляцию , чистить кжш и пул я тоже пробовал)

в метаданных объекта тоже не нашел такой ключ

Изображение удалено.

Нравится

5 комментариев
Лучший ответ

Dima Avdoshin,

Это не простой вопрос, разбирайтесь как создается раздел и смотрите что пошло не так. Создайте на тестовой среде отдельно новый раздел и увидите на каких таблицах он строится и какие данные привязаны.

Надо смотреть таблицы SysModule, SysModuleEdit, SysModuleEntity, что там не так с вашим разделом.

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

Можете установить пакет "Custom" текущим и попробовать зайти в мастер. Если ошибке не будет, то это ваш случай

Сломали значит раздел. Подробней опишите последовательность действий и проблему.

Полозюков Евгений Петрович,

Последнее что я делал с этим объектом,  создавал на основании объекта, который использовался для детали сам раздел


 

Дмитрий А.,

нет, не вышло

Dima Avdoshin,

Это не простой вопрос, разбирайтесь как создается раздел и смотрите что пошло не так. Создайте на тестовой среде отдельно новый раздел и увидите на каких таблицах он строится и какие данные привязаны.

Надо смотреть таблицы SysModule, SysModuleEdit, SysModuleEntity, что там не так с вашим разделом.

Показать все комментарии

В бизнес-процессе нужно было обнулить у контрагента поле-ссылку на другого клиента, имеющее тип Id. Для  этого выполнил запись в поле значения Guid.Empty. При этом поле пустым не стало, а в него записалось что-то вроде "00000-000000000-0000-00000".  И все бы ничего, можно и такое значение считать пустой ссылкой. Но при слиянии этого контрагента с другим,  система почему-то автоматически в поле ссылки результирующего контрагента проставила эти нули, а не вполне конкретную ссылку из второго контрагента. При этом не было даже запроса, какую из ссылок выбрать.

Вопрос: как в блоке Изменение данных бизнес-процесса записать в поле ссылки (ID) реально пустое значение?

Нравится

3 комментария

Илья, странно, что у Вас записалось «00000-000000000-0000-00000». Вы уверены, если посмотреть в базе, там тоже так?

Если именно так, то либо на этом поле отключена проверка целостности и в него можно писать любые Guid, либо в справочнике есть запись с Id «00000-000000000-0000-00000» и для системы такое значение не отличается от другого заполненного.

Пишите null

Дело в том, что в языке C# нет понятия NULL - для переменных разных типов NULL выражается по разному:

  1. Для справочных полей это Guid.Empty
  2. Для строковых полей это String.Empty
  3. Для полей с типом «Дата/время» это DateTime.MinValue
  4. Для логических полей «пустого»поля нет (нужно указывать значение false).

Но почему у Вас при вставке Guid.Empty реально в базу попал такой Guid, нужно разбираться. Если поле с ограничением целостности по связям и в справочнике такой записи нет, такого быть не должно.

Показать все комментарии

Добрый день!

Пробую реализовывать запрос к данных через ESQ таким образом:

var esq = Ext.create("Terrasoft.EntitySchemaQuery", {

                    rootSchemaName: "UsrTbl1"

                });

                esq.addColumn("Id");

                esq.addColumn("UsrPar1");esq.addColumn("UsrInfoId");

                esq.addColumn("UsrValueList.Name");//вот с такими строками уже начинается проблема

esq.filters.addItem(Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "UsrValueList.Name", "значение1"));//и с такими фильтрами

 

Если нужно получить значение колонок с таблицы - rootSchemaName, то не вопрос.

Проблемы начинаются, когда пытаюсь использовать прямые ссылки или в одной запросе получать GUID, а во втором его использовать.

GUID  видимо со String плохо понимают друг друга. Если ли примеры их нормального совместного использования в рамках ESQ?

Можно ли как-то понять причины неработоспособности прямых ссылок? Или хотя бы понять как с GUID быть? Даже если я значение GUID пытаюсь вставлять так, то не работает:

esq.filters.addItem(Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "UsrInfoId", "337ED96B-B658-48B0-BBB6-7FACF918C735"));

Нравится

2 комментария
Лучший ответ

Eсли нужно получить справочную колонку, то её название нужно указывать без приставки "Id", как в схеме таблицы:

esq.addColumn("UsrInfo")

Аналогично и с фильтрами:

esq.filters.addItem(Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "UsrInfo", "337ED96B-B658-48B0-BBB6-7FACF918C735"));

Но обратите внимание, что, если у Вас фильтр построен по обратным связям, то можно писать 2 способами.

1. Через Id и тогда в качестве значения фильтра указываем Id:

var shipment = this.get("BTShipment");

sampleESQ.filters.addItem(sampleESQ.createColumnFilterWithParameter(

                    this.Terrasoft.ComparisonType.EQUAL, "[BTSampInShipment:BTSampleID].BTShipment.Id", shipment.value));

2. Через справочное поле и тогда в качестве значения указывать значение справочного поля:

var shipment = this.get("BTShipment");

sampleESQ.filters.addItem(sampleESQ.createColumnFilterWithParameter(

                    this.Terrasoft.ComparisonType.EQUAL, "[BTSampInShipment:BTSampleID].BTShipment", shipment));

А вообще, чтобы понять причину ошибки нужно отладиться на стороне клиента, если запрос уходит в базу данных, то посмотреть в SQL profiler, какой запрос идет в базу и какой результат работы этого запроса.

 

В js все Guid преобразуйте к нижнему регистру

те в вашем случае напишите что то типа esq.filters.addItem(Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "UsrInfoId", "337ed.....

Eсли нужно получить справочную колонку, то её название нужно указывать без приставки "Id", как в схеме таблицы:

esq.addColumn("UsrInfo")

Аналогично и с фильтрами:

esq.filters.addItem(Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "UsrInfo", "337ED96B-B658-48B0-BBB6-7FACF918C735"));

Но обратите внимание, что, если у Вас фильтр построен по обратным связям, то можно писать 2 способами.

1. Через Id и тогда в качестве значения фильтра указываем Id:

var shipment = this.get("BTShipment");

sampleESQ.filters.addItem(sampleESQ.createColumnFilterWithParameter(

                    this.Terrasoft.ComparisonType.EQUAL, "[BTSampInShipment:BTSampleID].BTShipment.Id", shipment.value));

2. Через справочное поле и тогда в качестве значения указывать значение справочного поля:

var shipment = this.get("BTShipment");

sampleESQ.filters.addItem(sampleESQ.createColumnFilterWithParameter(

                    this.Terrasoft.ComparisonType.EQUAL, "[BTSampInShipment:BTSampleID].BTShipment", shipment));

А вообще, чтобы понять причину ошибки нужно отладиться на стороне клиента, если запрос уходит в базу данных, то посмотреть в SQL profiler, какой запрос идет в базу и какой результат работы этого запроса.

 

Показать все комментарии

Сущности в системе идентифицируются Guid. который, будучи преобразованным в строку, имеет вид типа "846d8d33-004b-4a3e-b778-10cfd163f3bb" (буквы строчные, в таком виде он фигурирует, например, в параметрах запросов http)

С другой стороны в БД сущности хранятся с первичным ключем, построенным на id varchar2(38), но содержиное там заключено в фигурные скобки и буквы заглавные.

Есть ли стандартная функция преобразования одного в другое? В запрос нужно передать Id текущего контакта, но "{"+UserConnection.CurrentUser.ContactId.ToUpper()+"}" выглядит достаточно неуклюже.

Нравится

12 комментариев

Могу предложить "элегантный костыль":

string contact = "846d8d33-004b-4a3e-b778-10cfd163f3bb";

string result = String.Join(String.Empty, "{", contact.ToUpper(), "}");

Если используете механизмы EntityShchemaQuery или Select/Insert/Update/Delete, то ничего преобразовывать не нужно, в функции передаётся переменная типа Guid и при генерации SQL в нужном формате подставится само. Если же самостоятельно создаёте SQL, воспользуйтесь своим кодом или советом выше.

Эелегантность костыля в виде сокращения записи обращения к переменной иррелевантна задаче :)

Меня больше интересовал источник подобных сложностей, почему сразу было не привести к одному формату? Ведь была ж какая-то причина?

Причина в том, что основная поддерживаемая база  — MS SQL, где есть тип «uniqueidentifier» и база поймёт вставку в любом формате. А поддержка Oracle добавлена опционально.

В этом и была суть вопроса: если в Oracle используется просто текст, какая разница, что туда писать? Зачем эти скобочки? Чтобы что-то в базе посмотреть, скопировать Id из URL не получится, это минус. Как и при склеивании ESQ и Select. А плюсы вообще есть?

Этот текст, хоть и не является отдельным типом «uniqueidentifier», но служит в качестве первичного или внешнего ключа. Соответственно, если писать в двух полях один GUID разным способом, связи между ними не получится.

Зверев Александр,

В каких 2-х полях??? Почему не писать ОДНИМ способом, в нижнем регистре и без скобок? Везде.

В версии для MS SQL пишите как вам нужно, а в Oracle — именно требуемым способом.

Зверев Александр,

Спасибо, я ожидал компетентный ответ, а не бессмысленный совет следовать инструкциям, я им и так следую, но не могу понять необходимость такого усложнения и препятствия к его устранению. Если препятствий нет, то, думаю,  все, кто на Oracle, меня поддержат, было бы хорошо привести все к единому знаменателю.

Дмитрий, оно и приведено к единому знаменателю — с фигурными скобками в верхнем регистре. Нет смысла в версиях с 3.0 по 7.13 использовать один формат, а потом внезапно менять просто потому, что не нравятся скобки.

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

При обычной работе с форматом написания не сталкиваются никак, все C#-классы принимают значения типа Guid и преобразуют в нужный формат при генерации SQL автоматически. В чём именно негативное влияние фигурных скобок, Вы так и не объяснили. 

Вероятно, первоисточник именно такого написания — стандартная функция CreateGuid в Delphi, на котором была написана система Terrasoft 3.X. Она генерирует именно в таком формате. И в таблицу базы Firebird и Oracle, где нет встроенных типов для хранения GUID, так и записывали.

В Microsoft для C# рекомендуют для получения нужного формата использовать для переменной типа Guid метод ToString("N") в сочетании с String.ToUpper.

Показать все комментарии

Здравствуйте,

Всплывает ошибка при загрузке мастера редактирования карточки:

file: undefined
line: undefined
column: undefined
message: Элемент с ключом 33e46153-d870-42af-a250-8d8a9ecae940 Не существует 
 date: Thu Nov 15 2018 16:02:43 GMT+0500 (Екатеринбург, стандартное время)
moduleId: undefined
moduleName: undefined





Пишет что id не найден, смотрел в БД, таблицу SysSchema там реально этого UId нету, но зато есть эта карточка но с другим Id

Почему так могло произойти ? И как это можно исправить ?



Изображение удалено.





Изображение удалено.

Нравится

2 комментария

Уточните, возникают ли какие-то ошибки в консоли просто при открытии этой карточки редактирования?

Возможно, что-то не перенеслось, если эти карточки переносили на основной сайт с базы разработки. 

Попробуйте сравнивать наполнение системных таблиц, связанных с разделами (вроде SysModule, SysModuleEdit и т.д.) для этого и для нормально работающего разделов. Либо произведите автоматический поиск по всем полям всех таблиц базы, чтобы найти, где именно записан этот ID 33e46153-d870-42af-a250-8d8a9ecae940.

Показать все комментарии

Приветы,

 

Подскажите плиз, как правильно сделать, создал объект наследуемый от базового и добавил поле BpCandidate как строка 50 символов в конструкторе объекта.

 

Пробовал сделать поле типа справочник и тогда оно становится Guid в коде

В следующем коде было вместо TEXT, у поля BpCandidate указан GUID

Так вот в консоли хрома видел ошибку уровня c#, а именно System.String не могу преобразовать в System.Guid и как быть? 

 

Удалив столбец, пересохранив и добавив его снова как строка 50 символов и вернув ТЕКСТ вместо ГУИД все заработало, но как быть с гуидами в инсерт запросами???

 

insertCount: function (candId) {

                this.logStep('insertCount started...');

                var insertQuery = this.Ext.create("Terrasoft.InsertQuery", {

                    rootSchemaName: "BpCandidateCall"

                });

                insertQuery.setParameterValue("CallCount",

                    1,

                    this.Terrasoft.DataValueType.INTEGER);



                insertQuery.setParameterValue("BpCandidate",

                    candId,

                    this.Terrasoft.DataValueType.TEXT);

                var dt = new Date();

                insertQuery.setParameterValue("CallDate",

                    dt,

                    this.Terrasoft.DataValueType.DATE);

                insertQuery.setParameterValue("CallTime",

                    dt,

                    this.Terrasoft.DataValueType.TIME);

                insertQuery.execute(function () {

                    //this.loadActivities();

                }, this);

                this.logStep('insertCount finished...');

            },

Нравится

1 комментарий

А что если колонка в базе будет GUID, а в коде выше DataValueType.TEXT?

Показать все комментарии
Идея
Не планируется

Если добавить возможность в фильтрах сравнивать Guid'ы по больше/меньше то появится возможность довольно просто реализовать цикл перебора записей в БП (сортировка по Id + Id > Id_спрошлойитерации). Сейчас для них присутствуют возможности сравнения как для строки, что не очень юзабельно.Ну или сам функционал перебора выборок.

9 комментариев

А разве Guid'ы генерируются по-порядку?

"Владимир Соколов" написал:

А разве Guid'ы генерируются по-порядку?


для цикла достаточно того, что они сортируются и сравниваются больше/меньше по одному и тому же алгоритму (хотя я не проверял достаточно дотошно)

правда, есть такой момент, что выборка может измениться, пока она перебирается. И хотя это никак не помешает процессу, но может давать несколько неожиданные результаты: 1) обработается больше записей, чем ожидалось на момент начала цикла (если, например, перед циклом было выбрано кол-во записей для выборки) 2) какие-то из вновь добавленных записей не обработаются, т.к. их ИД будет меньше ИД записи, обрабатываемой в текущий момент

Вообще, длинные циклы на уровне движка БП — не лучшая идея. Для этого больше подходит блок БП «скрипт» с нужным программированием внутри.

"Зверев Александр" написал:

Вообще, длинные циклы на уровне движка БП — не лучшая идея. Для этого больше подходит блок БП «скрипт» с нужным программированием внутри.


1) это если ты можешь написать этот код.
2) цикл вовсе не обязан быть длинным

Здравствуйте!

Сравнивайте по полю "Дата изменения". Точность этого поля - милисекунды. По этой причине нет двух записей с одинаковой датой модификации.

Дмитрий, информацию передали в департамент разработки для рассмотрения реализации.

Здравствуйте! 

Пока не планируем давать возможность в фильтрах сравнивать Guid'ы по больше/меньше.

Но планируем в ближайший версиях дать возможность пользовательскими средствами настраивать обработку коллекций записей. А именно: научим Чтение данных формировать коллекции и доработаем элемент Подпроцесс, в рамках которого можно будет запустить множество экземпляров процесса (multi instance subprocess).  

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

 

Марина Бельмега,

конечно, как и указано в топике

Показать все комментарии

Коллеги, здравствуйте.

В ходе выполнения различного рода задач может пригодится скрипт, который выполнит поиск заданного идентификатора по всей базе данных (в колонке с определенным названием).

DECLARE @COLUMN_NAME NVarChar(100) = 'Id'
DECLARE @COLUMN_VALUE NVarChar(100) = '8F2E3098-932C-49A8-8D06-B40462DA98CD'

DECLARE @tableName VARCHAR(50)
DECLARE tablesCursor CURSOR LOCAL FORWARD_ONLY STATIC FOR
               
                SELECT table_name = sysobjects.name
                FROM sysobjects
                JOIN syscolumns ON sysobjects.id = syscolumns.id        
                WHERE sysobjects.xtype='U'
                AND syscolumns.name = @COLUMN_NAME

OPEN tablesCursor
FETCH NEXT FROM tablesCursor INTO @tableName

WHILE @@FETCH_STATUS = 0
BEGIN  
               
                EXEC ('DECLARE @recordCount INT;
                               DECLARE @quotesChar CHAR = char(39);
                               DECLARE @tabChar CHAR = char(9);
                               BEGIN TRY
                                               SET @recordCount =
                                                               (SELECT COUNT(*)
                                                               FROM ['
+ @tableName + '] where ' + @COLUMN_NAME + ' = ''' + @COLUMN_VALUE + ''')
                                               IF @recordCount > 0
                                               BEGIN                                                  
                                                               PRINT '
'''
                                                               PRINT '
'-- ' + @tableName + ':''
                                                               PRINT '
'     SELECT * FROM ' + @tableName +
                                                                                                              ' WHERE ' + @COLUMN_NAME +
                                                                                                              ' = '' + @quotesChar + ''' + @COLUMN_VALUE + ''' + @quotesChar + ''''                                          
                                                               PRINT '
'     -- Количество строк в запросе: '' + CAST(@recordCount as VARCHAR(5))
                                               END
                               END TRY
                               BEGIN CATCH                                  
                               END CATCH;                      
                               '
);
                FETCH NEXT FROM tablesCursor INTO @tableName
END

CLOSE tablesCursor
DEALLOCATE tablesCursor

Нравится

Поделиться

0 комментариев
Показать все комментарии