Имя: Пароль:
1C
1С v8
Поиск в ВИДе (внешнем источнике данных): не находится запись с id = 0
, , ,
0 Cyberhawk
 
29.04.21
16:46
Во внешней БД MSSQL создать таблицу с двумя колонками:
1. "id", тип (int), первичный самовозрастающий ключ, у которого в настройках (identity specification) указать: identity seed = 0, identity increment = 1
2. "price", имя и тип не имеют значения, но для простоты пусть это будет число (int)

Подключаем эту таблицу к любой базе 1С, поддерживающей внешние источники данных (~8.3.5+): в метаданных указываем, что таблица - это объектные данные, поле ключа = id, только чтение для этого поля выставляем в истину.

Добавляем в таблицу пару записей:
id = 0, price = 100
id = 1, price = 200

Важно, чтобы в таблице образовалась запись с id = 0.

-------
Все написанное выше можно пропустить, а для эксперимента взять любую существующую у вас во внешней БД таблицу, в которой есть запись со значением в поле ключа = 0 (число ноль).

Далее (суть): выполняем в предприятии код https://paste1c.ru/1e868lb7ocjn


ИмяВИДа = "DWH";
ИмяТаблицыВИДа = "Table1";
ИмяПоляСДанными = "price";

//ОчиститьСообщения();

ТаблицаВИД = ВнешниеИсточникиДанных[ИмяВИДа].Таблицы[ИмяТаблицыВИДа];

ЗначениеДляПоиска1 = 100;
ЗаписьВИДСсылка1 = ТаблицаВИД.НайтиПоПолю(ИмяПоляСДанными, ЗначениеДляПоиска1);
Сообщить("Пустая ссылка: " + ЗаписьВИДСсылка1.Пустая());

ЗначениеДляПоиска2 = 200;
ЗаписьВИДСсылка2 = ТаблицаВИД.НайтиПоПолю(ИмяПоляСДанными, ЗначениеДляПоиска2);
Сообщить("Пустая ссылка: " + ЗаписьВИДСсылка2.Пустая());

ЗначениеДляПоиска3 = 777;
ЗаписьВИДСсылка3 = ТаблицаВИД.НайтиПоПолю(ИмяПоляСДанными, ЗначениеДляПоиска3);
Сообщить("Пустая ссылка: " + ЗаписьВИДСсылка3.Пустая());


Будут выданы следующие сообщения:

Пустая ссылка: Да
Пустая ссылка: Нет
Пустая ссылка: Да

А ожидалось, что будут сообщения:

Пустая ссылка: Нет
Пустая ссылка: Нет
Пустая ссылка: Да

Т.е. если в результате поиска найдена запись с id = 0, то она трактуется платформой как пустая ссылка.

Платформа: 8.3.15.1830
Режим совместимости: 8.3.9

Кто может проверить - проверьте, пожалуйста, у вас так же ведет себя платформа?
1 Вафель
 
29.04.21
16:49
а там точно 0 а не null?
2 Cyberhawk
 
29.04.21
17:03
3 ДенисЧ
 
29.04.21
17:14
"Платформа: 8.3.15.1830
Режим совместимости: 8.3.9"

Это ты кого покемоном назвал??
4 Cyberhawk
 
29.04.21
17:18
Удалось обойти такое поведение, в метаданных конфигурации указав в качестве поля ключа не колонку "id", а любую другую колонку, которая не содержит число ноль.
После этого приведенный выше код стал работать ожидаемо (запись стала находиться).
5 TormozIT
 
гуру
29.04.21
18:55
Пустое значение типа колонки таблицы внешнего источника у 1С трактуется как пустая ссылка - так уже давно работает. Конечно в этом есть неудобства. Но пустая ссылка ссылочному типу (объектной таблице) необходима. Как еще ее можно реализовать кроме как пустым значением типа ключевого поля?
6 Ненавижу 1С
 
гуру
29.04.21
22:08
(5) как у всех остальных людей вне 1с - через null
7 TormozIT
 
гуру
29.04.21
22:39
(6) пустая ссылки и NULL - разные значения. А NULL - вообще особое значение. Его уж точно нельзя использовать для обозначения пустой ссылки, иначе левое соединение будет давать пустые ссылки вместо NULL.
8 acht
 
29.04.21
23:37
(6) > как у всех остальных людей вне 1с
Это у тех, кто в своем стеке внезапно изобрел и одновременно использует null и System.DbNull м вдобавок не может расклеить в запросах NULL и пустую строку?

Ну-ну.
9 BeerHelpsMeWin
 
29.04.21
23:39
Тоже пришел к тому, что в ВИДах стоит использовать свое 1с-ное поле ключа.
10 BeerHelpsMeWin
 
29.04.21
23:40
Но у меня только одна сторона пишет, а вторая читает. Если обе будут писать-читать, будет непросто.
11 Конструктор1С
 
30.04.21
05:07
(6) null создаёт массу неудобств
12 Ненавижу 1С
 
гуру
30.04.21
06:36
(7) (8) (11) да я и не спорю
И ООП опасно и ФП вредно
13 Ненавижу 1С
 
гуру
30.04.21
06:42
(8) передёргиваете

null и System.DbNull - это интерпретация зависит от того какие средства вы используете. В СУБД самой такого нет

не может расклеить в запросах NULL и пустую строку - Оракал признал это архитектурной ошибкой. В других СУБД все ок
14 acht
 
30.04.21
07:49
(13) > передёргиваете
То есть предлагать выражать чисто 1Совсвое понятие "пустая ссылка" через NULL это одно, а
"интерпретация зависит от того какие средства вы используете" - это другое. Ну ок, что.
15 Ненавижу 1С
 
гуру
30.04.21
08:29
(14) и опять передёргиваете

В 1с есть и null и неопределено и пустые ссылки одновременно. В .net на уровне linq2sql не требуется работать с DbNull. На уровне ado.net другой разговор.
16 Cyberhawk
 
30.04.21
09:31
(5) Могли бы возвращать Неопределено в методе НайтиПоПолю, если запись в таблице не найдена.
Выходит, что контракт описан не полностью: https://i.imgur.com/BJEGSRA.png
И пустая ссылка будет возвращаться если найдена запись, в поле ключа которой содержится пустое значение того типа, что задан для этого ключа в метаданных конфигурации.
17 Ненавижу 1С
 
гуру
30.04.21
09:43
(16) поэтому явные запросы предпочтительнее
18 Cyberhawk
 
30.04.21
09:45
(9) Ну столь радикально во всех случаях поступать все же, наверное, не стоит. Все-таки самовозрастающий первичный числовой ключ в MSSQL по умолчанию нумеруется с 1 (при создании новой таблицы).
Просто мне попалась таблица, где этот ключ начинается с нуля. И объектная модель поиска подложила вот такой сюрприз.
19 Cyberhawk
 
30.04.21
10:06
(17) Да, это кажется гораздо более универсальной альтернативой (4), благодарю.
Проверил: при отсутствии записи в ВИДе результат запроса пустой, иначе - непустой в любом случае (в результате запроса присутствует в т.ч. и "плохая" запись с id = 0).

Вывод: если в объектной таблице ВИДа потенциально может присутствовать запись со значением ключа, соответствующим пустому значению того типа, что указан в метаданных 1С для этого поля ключа, то не следует пользоваться объектной моделью (НайтиПоПолю), а следует пользоваться запросом.
20 Ненавижу 1С
 
гуру
30.04.21
10:21
(19) + нужен аналог LINQ в 1С
21 Cyberhawk
 
17.05.21
08:56
Дополнение к (19) для истории: явный запрос отлично решает только задачу _поиска (проверки существования)_ существующей в ВИДе "плохой" (с id = 0) записи, но он не решает задачу манипулирования (получения, редактирования и обновления) такой записи.

Если интерактивно (в дин. списке) спозиционироваться на такой записи и перейти к ее редактированию (двойной клик или F2), то открывается форма создания новой записи (и, соответственно, в БД добавляется новая запись, а не обновляется интересующая нас "плохая").
Программно (через объектную технику работы с таблицей ВИДа, тип которой "Объектные данные") также невозможно получить объект такой записи (чтобы в нем какое-нибудь другое поле-реквизит поменять и обновить такую "плохую" запись в БД).

Поэтому рецепт из (19) - если нужна возможность не только проверять факт существования "плохой" записи, но и обновлять ее - нужно обязательно применять совместно с (4): в этом случае получится как интерактивно, так и программно получать и обновлять такую "плохую" запись. Также корректно будет работать и возможность ссылаться на эту запись в реквизитах других объектах конфигурации. Ну и, собственно, раз "НайтиПоПолю" тоже будет работать в этом корректно, то отпадает необходимость и переписывать код по рецепту из (19).
22 mistеr
 
17.05.21
09:14
(19) В этом случае не надо объявлять такую таблицу объектной. Объектная таблица по определению не должна содержать пустых ссылок, там ссылка это ПК.

Возможным архитектурным решением проблемы (0) была бы возможность в метаданных ВИД указывать, какое значение ключа примитивного типа будет использоваться в качестве "пустой ссылки".
23 Cyberhawk
 
17.05.21
09:25
(22) Сменить тип таблицы с объектной на необъектную тоже является рецептом лечения обозначенной в теме проблемы.
Только в этом случае нужно помнить, что придется переписать весь код по работе с этой таблицей ВИДа (который добавляет в нее или обновляет в ней записи).