Автоматизация бизнеса

Установка, настройка, внедрение и сопровождение любых конфигураций на платформе 1С:Предприятие.

Тел: 8(985)141-74-63 Дмитрий.   
ICQ:     552-608-881
e-mail: info@programmist1c.ru

Оплата после выполнения работы.

  •   Удаленный админ
  •   Карта сайта
  •   Контакты


  • Поиск
     

    Примеры программирования v8: Внешняя компонента для безопасной работы с базами данных по интерфейсу ADO

    Внешняя компонента для работы с базами данных по интерфейсу ADO. Приводит типы данных, умеет работать со ссылочными типами 1С:Предприятие.

    Автор статьи: romix | Редакторы: pectopatop Последняя редакция №8 от 13.10.07 | История URL: http://kb.mista.ru/article.php?id=454

    Внешняя компонента для безопасной работы с базами данных по интерфейсу ADO

    Ключевые слова: ADO, база, ошибка, поле, формат, adodb, connection

    http://x-romix.narod.ru/2007_01_25_ADO.rar (скачивать ЛЕВОЙ кнопкой мыши, размер ~109К)

    Чем лучше AdoDB.Connection?


    1) Умеет работать с различными типами данных, которые можно привести к строке, числу или дате.
    2) Не теряет точность для вещественных чисел
    3) Умеет читать дату и время из поля соответствующего типа.
    4) Содержит удобный интерфейс для обновления записей (Insert или Update в зависимости от наличия записи с указанными ключивыми полями).
    5) Поддерживает параметризацию (невозможно хакнуть программу подменой закавыченных значений).
    6) Умеет работать со ссылочными типами 1С:Предприятие (справочники, документы), упаковывая их в 16-символьное представление
    7) Предполагается переносимость между версиями 7.7 и 8.0 (пока не работает).

    Недостатки Windows-объекта ADODB.Connection


    1) Существует ошибка в реализации данного объекта:
    ADODB.Connection имеет свойство KeepConnection, которое подразумевает сохранение самим объектом своего
    состояния подключенности (т.е. если возникают
    разрывы связи, компонент должен сам переподключаться). К сожалению, как показывает практика, разрывы
    связи бывают довольно часто (несколько раз в сутки,
    по Ethernet). Ошибка заключается в том, что ADODB.Connection не переустанавливает связь при разрыве.
    Более того, ИНОГДА, даже если вы специально после
    разрыва связи выполните команды .Close и .Open, все равно ADODB.Connection не установить связь, а лишь
    создаст видимость ее установления: флаг Active=true.
    Но на деле, при проверке такого фиктивного соединения (например, запрос таблицы), вылетает ошибка об
    отсутствии связи. Ошибка эта повторяется довольно просто:

    - создайте Delphi-проект (или даже на другом языке) с использованием ADODB.Connection, таблицы и DBGrid, связанных друг с другом. Сделайте property AdoDB.Connection.LoginPrompt = false. И задайте такую строку соединения с БД, чтобы она ссылалась на базу данных по локальной сети.
    - добавьте Кнопку1 на форму, и поставьте на ее нажатие код, который будет выполнять методы .Close (в Try..Except..End), затем .Open у ADODB.Connection.
    - добавьте Кнопку2 на форму, поставьте на ее нажатие код, который выведет состояние свойства ADODB.Connection.Active.
    - запустите программу, нажмите Кнопку1, соединение произойдет. Проверьте это, нажав Кнопка2.
    - теперь специально разорвите связь между вашим компьютером, и компьютером с БД. Как умеете: или выдерните прямо сетевой шнур, или отключите соединение..
    - проверьте состояние ADODB.Connection, нажав Кнопка2: оно будет все ще думать, что оно подключено к БД.
    - если вы затем вновь соедините сеть, то ADODB.Connection даже ничего и не заметит. А при попытке запроса через такое "убитое" соединение будет вылезать ошибка.

    Будьте внимательны! Учитывайте данную ошибку. (повторяется на версиях ADO - 2.5, 2.8)

    2) Кроме того, у ADODB.Connection существует свойство, которое указывает (в секундах) через какое время, если соединение не используется, оно само разорвет связь.
    Чтение записей
    
    Отличие от традиционного ADODB.Connection - умеет читать самые разные типы данных. 
    //*******************************************
    Процедура Сформировать()
        //Открываем соединение
        ado.Open("Driver={Microsoft Access Driver (*.mdb)};Dbq="+ф_ИмяMDB+";Uid=Admin;Pwd=;");
        
        таб=СоздатьОбъект("Таблица");
        таб.ИсходнаяТаблица("Таблица");
        таб.ВывестиСекцию("Шапка");
        таб.Опции(0);
        
        
         Запрос="SELECT * FROM ТестоваяТаблица;";
        ado.Execute(Запрос);
        
        Пока ado.EOF=0 Цикл //Цикл по записям 
            таб.ВывестиСекцию("Строка|Начало");
            зн=ado.GetField("id"); таб.ПрисоединитьСекцию("Строка|Данные");
            зн=ado.GetField("text1"); таб.ПрисоединитьСекцию("Строка|Данные");
            зн=ado.GetField("memo1"); таб.ПрисоединитьСекцию("Строка|Данные");
            зн=ado.GetField("Байт1"); таб.ПрисоединитьСекцию("Строка|Данные");
            зн=ado.GetField("Целое1"); таб.ПрисоединитьСекцию("Строка|Данные");
            зн=ado.GetField("ДлинноеЦелое1"); таб.ПрисоединитьСекцию("Строка|Данные");
            зн=ado.GetField("Single1"); таб.ПрисоединитьСекцию("Строка|Данные");
            зн=ado.GetField("Double1"); таб.ПрисоединитьСекцию("Строка|Данные");
            зн=ado.GetField("КодРепликации1"); таб.ПрисоединитьСекцию("Строка|Данные");
            зн=ado.GetField("ДатаВремя1"); таб.ПрисоединитьСекцию("Строка|Данные");
            зн=ado.GetFieldAsDateTime("ДатаВремя1"); таб.ПрисоединитьСекцию("Строка|Данные");
            зн=ado.GetField("Денежный1"); таб.ПрисоединитьСекцию("Строка|Данные");
            зн=ado.GetField("Логический1"); таб.ПрисоединитьСекцию("Строка|Данные");
            зн=ado.GetField("Действительное1"); таб.ПрисоединитьСекцию("Строка|Данные");
            ado.MoveNext(); //Переходим к след. записи 
        КонецЦикла;
    
      ado.Close(); //Закрываем соединение
      таб.Показать("Запрос");
    КонецПроцедуры
    
    
    Добавление записей
    
    В этом примере я использую параметризацию: Prepare и Bind. Это позволяет исключить атаки злоумышленников, или сбои в работе, если я по какой-то причине не проставлю кавычки для экранирования текстовых полей. Полноценная параметризация не реализована.
    //____________________________________________________________________________________________________
    Процедура ф_Добавить()
      //  //Открываем соединение
      ado.Open("Driver={Microsoft Access Driver (*.mdb)};Dbq="+ф_ИмяMDB+";Uid=Admin;Pwd=;");
      
      //Подготовка запроса
      Запрос="INSERT INTO ТестоваяТаблица (text1,memo1,Байт1,Целое1,
    ДлинноеЦелое1, Single1, Double1,КодРепликации1,ДатаВремя1,Денежный1,
    Логический1,Действительное1) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)";
      ado.PrepareQuery(Запрос);
      ado.Bind("это text");
      ado.Bind("это memo");
      ado.Bind(257);
      ado.Bind(32767);
      ado.Bind(9999999);
      ado.Bind(12.34);
      ado.Bind(56.78);
      ado.Bind("{AB634001-F13D-11D0-A459-004095E1DAEA}");
      ado.Bind('26.01.2007');
      ado.Bind(33.33);
      ado.Bind(1);
      ado.Bind(111);
      ado.Execute();
      ado.Close(); //Закрываем соединение
        
    КонецПроцедуры
    
    
    Обновление записей
    
    Данный пример смотрит, есть ли запись с указанным ID. Если ее нет, то добавляет (Insert) ее, затем делает Update.
    //____________________________________________________________________________________________________
    Процедура ф_Обновить()
      //  //Открываем соединение
      ado.Open("Driver={Microsoft Access Driver (*.mdb)};Dbq="+ф_ИмяMDB+";Uid=Admin;Pwd=;");
         Запрос="SELECT id FROM ТестоваяТаблица WHERE id=?;";
         ado.PrepareQuery(Запрос);
        ado.Bind(1);
        ado.Execute();
        Если ado.EOF=1 Тогда
            Запрос="INSERT INTO ТестоваяТаблица (id) VALUES (?)"; 
            ado.PrepareQuery(Запрос);
            ado.Bind(1);
            ado.Execute();
        КонецЕсли;    
        
          Запрос="UPDATE ТестоваяТаблица SET "+
          "text1=?,memo1=?,Байт1=?,Целое1=?,ДлинноеЦелое1=?, Single1=?, Double1=?,
    КодРепликации1=?,ДатаВремя1=?,Денежный1=?,Логический1=?,Действительное1=?"+
          " WHERE id=?";
          
          ado.PrepareQuery(Запрос);
          
          ado.Bind("это text");
          ado.Bind("это memo");
          ado.Bind(257);
          ado.Bind(32767);
          ado.Bind(9999999);
          ado.Bind(12.34);
          ado.Bind(56.78);
          ado.Bind("{AB634001-F13D-11D0-A459-004095E1DAEA}");
          ado.Bind('26.01.2007');
          ado.Bind(33.33);
          ado.Bind(1);
          ado.Bind(111);
          ado.Bind(1);
        
          ado.Execute();
              
      ado.Close(); //Закрываем соединение
        
    КонецПроцедуры
    
    
    Удобное обновление записей
    
    Этот пример делает то же самое, что и предыдущий, но записан в более удобном для восприятия виде. 
    
    //____________________________________________________________________________________________________
    Процедура ф_Обновить1()
      //  //Открываем соединение
      ado.Open("Driver={Microsoft Access Driver (*.mdb)};Dbq="+ф_ИмяMDB+";Uid=Admin;Pwd=;");
      ado.OpenRec("ТестоваяТаблица");
      ado.KeyField("id", 1); //Ключевое поле
      ado.DataField("text1", "это текст");
      ado.DataField("memo1", "это memo");
      ado.DataField("Байт1", 255);
      ado.DataField("Целое1", 32767);
      ado.DataField("ДлинноеЦелое1", 88889999);
      ado.DataField("Single1", 12.34);
      ado.DataField("Double1", 56.78);
      ado.DataField("КодРепликации1", "{AB634001-F13D-11D0-A459-004095E1DAEA}");
      ado.DataField("ДатаВремя1", '26.01.1976');
      ado.DataField("Денежный1", 100.55);
      ado.DataField("Логический1", 1);
      ado.DataField("Действительное1", 1234);
      ado.SaveRec();
      ado.Close(); //Закрываем соединение
        
    КонецПроцедуры
    
    
    Работа со ссылочными типами
    
    
    Приведенный ниже пример обновляет таблицу, которая содержит код, наименование и
     ссылку на элемент товаров. Метод GetFieldAsObject("Товар")
     извлекает товар из таблицы как ссылку на объект 1С:Предприятие! 
    
    //____________________________________________________________________________________________________
    Процедура ф_Реквизиты()
      //Открываем соединение
      ado.Open("Driver={Microsoft Access Driver (*.mdb)};Dbq="+ф_ИмяMDB+";Uid=Admin;Pwd=;");
      спр=СоздатьОбъект("Справочник.Товары");
      спр.ВыбратьЭлементы();
      Пока спр.ПолучитьЭлемент() = 1 Цикл
         Запрос="SELECT Код FROM Товары WHERE Код=?;";
         ado.PrepareQuery(Запрос);
        ado.Bind(0+спр.Код);
        ado.Execute();
        Если ado.EOF=1 Тогда
            Запрос="INSERT INTO Товары (Код) VALUES (?)"; 
            ado.PrepareQuery(Запрос);
            ado.Bind(0+спр.Код);
            ado.Execute();
        КонецЕсли;    
        
          Запрос="UPDATE Товары SET "+
          "Товар=?,Наименование=?"+
          " WHERE Код=?";
          
          ado.PrepareQuery(Запрос);
          
          ado.Bind(спр.ТекущийЭлемент());
          ado.Bind(спр.Наименование);
          ado.Bind(0+спр.Код);
        
          ado.Execute();
      КонецЦикла;
    
    //Читаем элементы
         Запрос="SELECT * FROM Товары";
        ado.Execute(Запрос);
        
        Пока ado.EOF=0 Цикл //Цикл по записям 
            зн=ado.GetField("Код"); Сообщить("Код="+зн+" ");
            зн=ado.GetField("Наименование"); Сообщить("Наименование="+зн+" ");
            зн=ado.GetFieldAsObject("Товар"); Сообщить("Товар="+зн+" ");
            ado.MoveNext(); //Переходим к след. записи 
        КонецЦикла;
      ado.Close(); //Закрываем соединение
    КонецПроцедуры
    
    
    То же самое, с использованием OpenRec-SaveRec. 
    
    //____________________________________________________________________________________________________
    Процедура ф_Реквизиты1()
      //Открываем соединение
      ado.Open("Driver={Microsoft Access Driver (*.mdb)};Dbq="+ф_ИмяMDB+";Uid=Admin;Pwd=;");
      
      //Пишем товары в таблицу
      спр=СоздатьОбъект("Справочник.Товары");
      спр.ВыбратьЭлементы();
      Пока спр.ПолучитьЭлемент() = 1 Цикл
          
          ado.OpenRec("Товары");
          ado.KeyField("Код", 0+спр.Код); //Ключевое поле
          ado.DataField("Наименование", спр.Наименование);
          ado.DataField("Товар", спр.ТекущийЭлемент());
          ado.SaveRec();
          
      КонецЦикла;
    
    //Читаем элементы
         Запрос="SELECT * FROM Товары";
        ado.Execute(Запрос);
        
        Пока ado.EOF=0 Цикл //Цикл по записям 
            зн=ado.GetField("Код"); Сообщить("Код="+зн+" ");
            зн=ado.GetField("Наименование"); Сообщить("Наименование="+зн+" ");
            зн=ado.GetFieldAsObject("Товар"); Сообщить("Товар="+зн+" ");
            ado.MoveNext(); //Переходим к след. записи 
        КонецЦикла;
      ado.Close(); //Закрываем соединение
    КонецПроцедуры
    
    Получение имен полей по их номеру (13.02.2007)
    
    
         Запрос="SELECT * FROM ТестоваяТаблица;";
        ado.Execute(Запрос);
        
        Для й= 0 По ado.КоличествоПолей-1 Цикл
            Сообщить("Имя поля: "+ado.ИмяПоля(й));
        КонецЦикла;
    
    
    21.02.18 | 10:31


    30.11.16 | 20:25


    28.11.16 | 09:22


    26.11.16 | 08:19


    22.11.16 | 20:17


    19.11.16 | 10:14


    18.11.16 | 20:09




    Внедрение 1С Автоматизация 1С Доработка 1С Сопровождение 1С Обслуживание 1С Программирование 1С 8 Hастройка 1С Карта сайта Контакты