Использование технологии LinqToSql для прямого доступа к данным 1С:Предприятие




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2024-01-05 12:44:55

global $wpdb2;
global $failure;
global $file_hist;

/////  echo '<H2><b>Старт загрузки</b></H2><br>';

$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
/////   echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}

$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
/////   echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}

/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
/////   echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
/////    echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist);   ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7];    ////получаем размер файла
$m_mtime_file=$masiv_data_file[9];   ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file

/////   echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
/////   echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
/////   echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);

if ($results)
{   foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));

////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
/////   echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
/////   echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}

////загружаем данные
$table='vin_history';         // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация     // (путь от корня web-сервера)
$delim=';';          // Разделитель полей в CSV файле
$enclosed='"';      // Кавычки для содержимого полей
$escaped='\

21 Comments

  1. artbear

    А почему отнесена к разработкам, хотя это статья либо веб-закладка??

    Reply
  2. Elisy

    (1) Не знаю. Определена публикация: веб-закладка

    Reply
  3. Душелов

    Я бы отнес это к веб-закладке. Но никак не к статье.

    Reply
  4. German

    8) Да, не знал про эту технологию…

    ИМХО Проще создать представления(View), их можно не только через С# использовать, а на простом T-SQL. Явно было представлено в ранних версиях Ei

    Reply
  5. Elisy

    (4) Для конкретного случая .net framework + MS SQL не проще. Для остальных случаев, куда не дошел Linq, скорее всего проще, спорить не буду.

    Разработчики C# могут оценить:

    Следующая C# конструкция свяжет справочники Номенклатура+ЕдиницыИзмерения, задаст параметр отбора, а на выходе выдаст готовые объекты Товар:

    var nomenclatureModel = from Номенклатура in dc.GetTable<СправочникЕдиницыИзмерения>().Where(item => item.Родитель == nom.Ссылка)

    join Еи in dc.GetTable<СправочникЕдиницыИзмерения>() on Номенклатура.ЕдиницаХраненияОстатков equals Еи.Ссылка

    select new Товар { Ссылка = new Guid(Номенклатура.Ссылка.ToArray()), Наименование = Номенклатура.Наименование, ЕИ = Еи.Наименование };

    При этом система .net framework внутри себя сгенерирует SQL-выражение, сделает запрос к БД, преобразует данные в нужный формат Товар:

    {SELECT [t0].[_IDRRef], [t0].[_Description] AS [Наименование], [t1].[_Description] AS [ЕИ]

    FROM [dbo].[_Reference53] AS [t0]

    INNER JOIN [dbo].[_Reference35] AS [t1] ON [t0].[_Fld720RRef] = [t1].[_IDRRef]

    WHERE [t0].[_ParentIDRRef] = @p0

    }

    Reply
  6. Душелов

    Идея, конечно, хорошая, но только для чтения. Писать бы я не стал.

    Reply
  7. Gilev.Vyacheslav

    http://v8.1c.ru/predpriyatie/questions_licence.htm

    Лицензионное соглашение не позволяет использовать недокументированные фирмой «1С» средства для построения решений на платформе 1С:Предприятие. Это означает, что средства СУБД (или любые другие внесистемные средства) можно использовать только в том случае, если документация по продуктам линейки «1С:Предприятие» (включая ИТС) содержит явную рекомендацию использовать данное средство для решения данной задачи.

    Во всех остальных случаях лицензионное соглашение позволяет использовать для построения решений только штатные средства платформы. В частности, можно обращаться к данным информационной базы только при помощи объектов «1С:Предприятия», специально предназначенных для работы с данными (запросы, справочники, документы и т.д.). Нельзя обращаться к данным информационной базы напрямую, минуя уровень объектов работы с данными «1С:Предприятия» — например при помощи средств СУБД или при помощи внешних компонент, которые реализуют прямой доступ к СУБД. Это ограничение распространяется на любые действия с данными, в том числе на изменение их структуры, а так же на чтение или изменение самих данных информационной базы или служебных данных «1С:Предприятия».

    Данное ограничение необходимо для обеспечения стабильности работы механизмов системы, осуществления поддержки и возможности перехода на новые версии «1С:Предприятия».

    Reply
  8. Gilev.Vyacheslav

    так что у этого «мало исследованного» способа еще другой побочный эффект, с новыми правилами 1с можно огрести 😀

    Reply
  9. Elisy

    (7)(8) Получить xml-файл на платформе 1С — это не нарушение правил 1С. Запись xml-файла — это документированные функции. Внешние обработки — это также построенные по технологии 1С решения. Запуск такой обработки не противоречит правилам 1С. Все остальное — вотчина .net framework, Visual Studio, SQL Server и Microsoft.

    Компании 1С следует обратиться с официальным письмом к корпорации Microsoft с требованием блокировать в новых версиях MSSql, .net framework и Visual Studio доступ к базам данных 1С. А равно как и в срочном порядке выпустить сервис паки к существующим версиям, реализующим такие ограничения.

    Продукты Microsoft лицензируются отдельными соглашениями и компания 1С не вправе предъявлять подобного рода претензии к ним.

    Reply
  10. Elisy

    (6) Я бы тоже записывать пока не стал. Подождал бы, пока другие запишут и скажут результат 🙂

    Reply
  11. artbear

    (7) ОФФ. ИМХО эта лицензия в какой-то мере нарушает закон об авторском праве 🙁

    Но у 1С явно юристы лучше, чем у тех, кто попробует с этим побороться 🙁

    Reply
  12. JohnyDeath

    (7) Офигеть. А это нормально? СУБД-то не от 1С, с чего это вдруг я не могу выбирать из неё данные своими средствами?

    Вячеслав, у тебя на сайте много хорошего и полезного материала по 1С 8, где ты используешь не только 1С для оценки эффективности и оптимизации работы базы. За это ты тоже можешь отгрести?

    Reply
  13. Elisy

    (7) Данное требование лицензионного соглашения противоречит Статье 1334 п.1 «Исключительное право изготовителя базы данных» ГК РФ часть 4, а также Статье 25 п.1 и п.3 «Свободное воспроизведение программ для ЭВМ и баз данных. Декомпилирование программ для ЭВМ» Закона об авторском праве и смежных правах.

    В Гражданском Кодексе сказано:

    «Изготовителю базы данных, создание которой (включая обработку или представление соответствующих материалов) требует существенных финансовых, материальных, организационных или иных затрат, принадлежит исключительное право извлекать из базы данных материалы и осуществлять их последующее использование в любой форме и любым способом».

    Reply
  14. Gilev.Vyacheslav

    (12) да, мне тоже может попасть, по этой причине обработку locks уже убрал с сайта

    Reply
  15. Gilev.Vyacheslav

    (13) российский гражданский кодекс какую предусматривает ответственность за нарушение?

    а я вот докадываюсь, чем грозит разборки с 1С,

    сейчас это основной обвинитель по делам с нарушениями ЛС в России

    Reply
  16. Elisy

    (15) Гражданский кодекс ничего не говорит об ответственности. За это отвечает административный кодекс, который изучать нужно. Даже при самом худшем раскладе, до которого доведут самые лучшие адвокаты 1С — нарушение данного пункта лицензионного соглашения не уголовное преступление. А на месте таких адвокатов впутываться в дела с сомнительным результатом — работа неблагодарная. Другой вопрос, кто-нибудь знает прецеденты конкретно по таким делам, доведенным до суда?

    Reply
  17. Rabajaba

    «1С-программистам легче переходить с 8.1 версии на Asp.Net, чем на 8.2, «благодаря» ограничениям и мешанине из серверного и клиентского кода в каждой форме» это минус, хотя статья понравилась.

    «мешанине» это вы как-то неверно готовите. Мне наоборот нравится, что 1С теперь УЧИТ писать архитектурно грамотно, разбивая всю работу БД на клиента и сервера. Что, в свою очередь, заставляет думать об объемах трафика и количестве вызовов между клиентом и сервером, что было довольно сложно оценить в 8.1.

    П.С. Серверный код для формы никто не заставляет писать в модуле формы.

    Reply
  18. soe

    при открытии обработки возникает ошибка:

    {Форма.Форма(7)}: Ошибка при вызове метода контекста (ЗагрузитьВнешнююКомпоненту): Ошибка при загрузке внешней компоненты

    ЗагрузитьВнешнююКомпоненту(«C:Program FilesElisy .Net Bridge SDKElisy.NetBridge.dll»);

    по причине:

    Ошибка при загрузке внешней компоненты

    Не подскажите причину?

    Reply
  19. Elisy
    soe пишет:

    при открытии обработки возникает ошибка: {Форма.Форма(7)}: Ошибка при вызове метода контекста (ЗагрузитьВнешнююКомпоненту): Ошибка при загрузке внешней компоненты ЗагрузитьВнешнююКомпоненту(«C:Program FilesElisy .Net Bridge SDKElisy.NetBridge.dll»); по причине: Ошибка при загрузке внешней компоненты

    Не подскажите причину?

    Нужно проверить:

    1. Установлен .Net framework 3.5 SP1?

    2. На Windows 7 с включенным UAC нужно устанавливать .Net Bridge с правами администратора. Только в этом случае Elisy.NetBridge.dll сможет прописаться в реестре.

    Reply
  20. maksar

    Интересно почитать, спасибо.

    Reply
  21. Elisy

    (20) Спасибо. Читайте статью на эту же тему в октябрьском номере журнала MSDeveloper

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *