12 февр. 2014 г.

Запись во внешний источник данных 1С, новые возможности

В 8.3.4 в свойствах объекта "Внешний источник данных" появилась вкладка "Функции". Для внешних таблиц MSSQL данный функционал позволяет подключить к 1С хранимые процедуры и функции на стороне SQL. В том числе и процедуры, содержащие запросы SQL на добавление и обновление данных внешней таблицы.


По сравнению с прошлым примером количество кода 1С уменьшится, поскольку подключение через COM-объект и формирование запросов SQL на стороне 1С нам больше не потребуется.

Для начала создадим тестовую таблицу с помощью скрипта в панели управления сервером SQL:

USE [test]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[tovar](
[id] [int] IDENTITY(1,1) NOT NULL,
[name] [nvarchar](max) NOT NULL,
[price] [numeric](18, 2) NULL,
 CONSTRAINT [PK_tovar] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO


Скрипт создания процедуры insert_tovar:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE insert_tovar

@name nvarchar(max),
@price numeric(18, 2)

AS
BEGIN

SET NOCOUNT ON;

INSERT INTO test.dbo.tovar
 ([name] ,[price])
 VALUES (@name, @price)

END
GO


Скрипт создания процедуры update_tovar:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE update_tovar

@id int,
@name nvarchar(max),
@price numeric(18, 2)

AS
BEGIN

SET NOCOUNT ON;

UPDATE test.dbo.tovar
  SET [name] = @name
 ,[price] = @price
WHERE id = @id

END
GO


Теперь переходим в 1С и добавляем внешний источник данных. Подключаем таблицу SQL:




Подключаем процедуры:


Далее, для таблицы dbo_tovar создаем формы списка и объекта. На форму списка вешаем команду "ДобавитьТовар" и обработку оповещения:

&НаКлиенте
Процедура ДобавитьТовар(Команда)
 
 ОткрытьФорму("ВнешнийИсточникДанных.test.Таблица.dbo_tovar.ФормаОбъекта", , ЭтаФорма);
 
КонецПроцедуры

&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
 
 Если ИмяСобытия = "ОбновитьВнешнийИсточникДанных_dbo_tovar" Тогда
  Элементы.Список.Обновить();
 КонецЕсли; 
 
КонецПроцедуры 

На форме объекта на командной панели размещаем команду "ЗаписатьТовар", для кнопки выставляем свойство "Кнопка по умолчанию":


&НаКлиенте
Процедура ЗаписатьТовар(Команда)
 
 ЗаписатьТоварНаСервере();
 Оповестить("ОбновитьВнешнийИсточникДанных_dbo_tovar");
 
КонецПроцедуры

&НаСервере
Процедура ЗаписатьТоварНаСервере()
 
 Если Объект.Ссылка.Пустая() Тогда
  ВнешниеИсточникиДанных.test.dbo_insert_tovar(Объект.name, Объект.price);
 Иначе
  ВнешниеИсточникиДанных.test.dbo_update_tovar(Объект.id, Объект.name, Объект.price);
 КонецЕсли;
 
КонецПроцедуры 

Для свойства реквизита "Объект" снимаем свойство "Сохраняемые данные", для поля "id" устанавливаем свойство "Только просмотр".


Готово, запускаем, тестируем. Для тестов использовался сервер MSSQL Server 2008 R2.


15 комментариев:

  1. В описание от 1С http://v8.1c.ru/o7/201402ext/index.htm редактируют записи интерактивно и программно средствами новой платфоры.
    Поставил последнюю (8.3.4.437), у меня внешний источник MS SQL открывается только для чтения. Хотя у них указано, что есть свойства таблицы: "Для всей таблицы - свойство ТолькоЧтение. ТолькоЧтение = Истина означает, что изменение данных в этой таблице невозможно".
    У меня эти свойств у таблиц нет(((.

    Где моя ошибка, не подскажите?

    ОтветитьУдалить
    Ответы
    1. День добрый,
      полагаю, в статье анонсирована возможность, которая появится в одной из будущих версий платформы.

      Удалить
    2. Спасибо. Давно жду такую возможность, увидел новость, побежал пробовать, но не тут то было...
      Думаю в 8.3.5 будет. По их плану выходит 11.04.14.

      Удалить
  2. 1С может использовать только хранимые функции (вызывает их через SELECT), а не процедуры.
    А в MS SQL запрешено использование INSERT и UPDATE в хранимых функциях...
    Так-точ предложенный способ к сожелению не работает

    ОтветитьУдалить
    Ответы
    1. Данный способ был успешно протестирован на MS SQL 2008.

      Удалить
  3. Добрый день! Подскажите пожалуйста... У меня MS SQL 2005, 1С 8.3 самописная, расположена на сервере Linux. Создала хранимую процедуру в MS SQL, проверила работоспособность, все хорошо. Создала в 1С внешний источник, пыталась автоматически получить список хранимых процедур, но получила список абры-кадабры, ладно, определила функция вручную, прописав в ней имя хранимой процедуры. Процедура должна выполнять вставку строки в таблицу MS SQL. В итоге, процедура отрабатывает, но выходит ошибка invalid cursor state. Посмотрели средствами MS SQL, процедура выполнилась из 1С без ошибок. Т.е. на стороне 1С наверно какая-то ошибка, в чем может быть проблема? На Linux установлен драйвер и прописан dsn, для подключения к внешнему источнику.

    ОтветитьУдалить
    Ответы
    1. И насколько правильным является, что я буду для каждой добавляемой строчки вызывать хранимую процедуру, таких строк за один раз около 200.

      Удалить
    2. Добавление массива строк оптимально осуществлять одним запросом, либо бить на блоки данных.

      Удалить
  4. А с помощью механизмов 1с это можно реализовать, не используя comобъекты?

    ОтветитьУдалить
    Ответы
    1. Кстати, а как быть в ситуации, когда установка поля идентификатора запрещена самой субд (IDENTITY_INSERT в MSSQL), но подобную манипуляцию нужно выполнять? Т.е. автоинкремент идентификатора не подходит.

      При попытке задать идентификатор таблицы получаем: Cannot insert explicit value for identity column in table 'table' when IDENTITY_INSERT is set to OFF

      Удалить
    2. Поставьте в свойствах такого поля таблицы внешнего источника признак "Только чтение".

      Удалить
    3. Но если я поставлю только чтение, то смогу его только читать, отдавая СУБД заботиться об установке уникального значение. А я хочу сам его устанавливать таким, как мне нужно...

      Удалить
    4. Поле с такими настройками заполняется механизмами SQL и не редактируется, даже через SQL Managment Studio.
      В вашем случае необходимо создавать таблицу без указания IDENTITY(1,1) для ключа. В этом случае контроль уникальности будет осуществляться, но значение автоматически не присваивается.

      Удалить
    5. Спасибо за хороший совет.

      Удалить