{"id":13446588,"url":"https://github.com/ivan816/simple-1c","last_synced_at":"2026-01-17T22:36:14.462Z","repository":{"id":87647844,"uuid":"61479227","full_name":"ivan816/simple-1c","owner":"ivan816","description":"Транслятор запросов и Linq-провайдер для 1С-Бухгалтерии","archived":false,"fork":false,"pushed_at":"2018-04-23T17:43:29.000Z","size":19498,"stargazers_count":63,"open_issues_count":4,"forks_count":15,"subscribers_count":24,"default_branch":"master","last_synced_at":"2025-11-27T13:57:09.137Z","etag":null,"topics":["1c","csharp","linq","sql"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ivan816.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2016-06-19T12:31:58.000Z","updated_at":"2025-10-14T09:42:41.000Z","dependencies_parsed_at":"2023-04-11T17:17:30.048Z","dependency_job_id":null,"html_url":"https://github.com/ivan816/simple-1c","commit_stats":null,"previous_names":["gusev-p/simple-1c"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/ivan816/simple-1c","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivan816%2Fsimple-1c","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivan816%2Fsimple-1c/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivan816%2Fsimple-1c/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivan816%2Fsimple-1c/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ivan816","download_url":"https://codeload.github.com/ivan816/simple-1c/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivan816%2Fsimple-1c/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28521160,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T22:11:28.393Z","status":"ssl_error","status_checked_at":"2026-01-17T22:11:27.841Z","response_time":85,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["1c","csharp","linq","sql"],"created_at":"2024-07-31T05:00:54.724Z","updated_at":"2026-01-17T22:36:14.446Z","avatar_url":"https://github.com/ivan816.png","language":"C#","readme":"﻿#Simple1C\n\n*This project is licensed under the terms of the MIT license.*\n\nУпрощаем интеграцию с 1С за счет двух основных функций:\n\n* умеем исполнять обычные запросы языка 1С (`выбрать * из Справочник.Контрагенты`)\nбез участия самой 1С - напрямую через СУБД. Это может быть удобно при использовании\n[механизма разделения данных](http://v8.1c.ru/overview/Term_000000788.htm) чтобы\nвыполнить запрос сразу на всех [областях](http://v8.1c.ru/overview/Term_000000790.htm)\nинформационной базы или даже на нескольких информационных базах, если\nиспользуется более одного сервера СУБД. Такая возможность становится особенно актуальной при\nбольшом числе различных организаций, работающих с одной типовой конфигурацией,\nнапример через технологию [1C-фреш](http://v8.1c.ru/fresh/whatis.htm).\n\n* если есть потребность заинтегрировать с 1С внешнее приложение, и это\nприложение написано на .NET, то одним из вариантов может быть использование 1С COM апи.\nЭто апи основано на интерфейсе [IDispatch](https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms221608(v=vs.85).aspx)\nи позднем связывании, поэтому любая опечатка в имени метода или свойства приводит к ошибке во время выполнения.\nМы решаем эту проблему путем генерации оберточных классов для всех объектов конфигурации. Эти\nклассы можно использовать как для сохранения новых данных, так и для выполнения запросов в\nстиле [LINQ](https://www.google.ru/url?sa=t\u0026rct=j\u0026q=\u0026esrc=s\u0026source=web\u0026cd=2\u0026cad=rja\u0026uact=8\u0026ved=0ahUKEwili-f_2tfPAhVICiwKHaHPB7QQFggnMAE\u0026url=https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FLanguage_Integrated_Query\u0026usg=AFQjCNEjvId7H8I66uhYbueZxwszChwoyg\u0026bvm=bv.135475266,d.bGg).\n\n##NuGet\n\nДля установки [Simple1C пакета](https://www.nuget.org/packages/Simple1C),\nвыполните следующую команду в [NuGet-консоли](http://docs.nuget.org/docs/start-here/using-the-package-manager-console)\n\n    PM\u003e Install-Package Simple1C\n\n##Simple1C.SQL\n\nПреобразуем запрос в формате языка запросов 1С в чистый sql и исполняем его на реальной СУБД.\nИспользуем [Irony](https://irony.codeplex.com) для синтаксического анализа и\nпостроения [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree).\n\nНа практике работает это следующим образом. Первым делом с помощью команды `gen-sql-meta`\nдостаем через COM метаданные по объектам конфигурации и сохраняем их\nв отдельную [схему](https://www.postgresql.org/docs/9.1/static/ddl-schemas.html) `simple1c` в sql базе данных\n(пока поддерживается только PostgreSQL).\n```\nGenerator.exe\n\t-cmd gen-sql-meta\n\t-connection-string \u003cбудет передан методу Connect объекта V83.COMConnector\u003e\n\t-db-connection-string \u003cдля подключения к sql СУБД\u003e\n```\nЭти метаданные нужны в первую очередь для установления соответствия между именами объектов и реквизитов\nконфигурации 1С и именами таблиц и колонок в БД. Затем для выполнения запроса\nиспользуем команду `run-sql` следующим образом:\n```\nGenerator.exe\n\t-cmd run-sql\n\t-connection-strings \u003cна какой базе выполнять запрос, можно передать несколько через запятую\u003e\n\t-query-file \u003cимя файла с запросом\u003e\n\t-result-connection-string \u003cкуда поместить результат\u003e\n\t-dump-sql true \u003cопционально, выводит фактически исполняемый sql-запрос для отладки\u003e\n```\nРезультат выполнения запроса помещается в таблицу в базе, указанной параметром result-connection-string.\nПока поддерживается только MS SQL Server в качестве такой базы. Имя таблицы берется из имени файла с запросом.\nОсновные возможности:\n\n* Поддерживается большая часть конструкций языка - все стандартные элементы sql (подзапросы, union, group by, order by и т.п.),\nоператоры Значение и Ссылка, функции ПРЕДСТАВЛЕНИЕ, ДАТАВРЕМЯ, ГОД, КВАРТАЛ и другие.\n\n* Поддерживается синтаксис для доступа к вложенным реквизитам через точку\n```\n\tselect ДоговорКонтрагента.Наименование from Документ.ПоступлениеТоваровУслуг\n\twhere Контрагент.ГоловнойКонтрагент.ИНН = \"7710967300\"\n```\nПри трансляции в sql к такому запросу будут добавлены необходимые цепочки join-ов на справочники\nконтрагентов и договоров.\n\n* Можно использовать как русский, так и аглийский варианты синтаксиса - `select * from Справочник.Контрагенты`\nэквиваленто `выбрать * из Справочник.Контрагенты`.\n\n* Если вы используете 1С-Фреш и у вас несколько sql баз, то можно передать их все в параметре connection-strings.\nВ этом случае запрос будет выпоняться параллельно на всех базах, а все результаты будут объеденены в одной общей таблице.\nМожно потом, например, через SQL Server Management Studio применить group by к этой таблице и получить\nгруппировку данных между различными базами.\n\n* Чтобы понять, какие объекты и реквизиты можно использовать в запросе, можно посмотреть в сгенерированные командой gen-sql-meta\nметаданные в схеме `simple1c`, а именно в таблицу tableMappings. В ней есть имена объектов, имена\nсоответствующих им таблиц и такое же соответствие для реквизитов и колонок в таблицах.\n\n* Оператор `Ссылка` можно использовать для ускорения выполнения запроса. Дело в том, что в 1С\nреквизит может не иметь фиксированного статического типа, а допускать сразу несколько типов.\nОсновной пример - это реквизит субконто, который для разных счетов может ссылается на разные\nобъекты конфигурации: Контрагент, Статья учета и т.п. Если в запросе\nесть обращение через точку к свойствам такого реквизита (`doc.Субконто1.Наименование`), то\nединственный вариант получить нужные данные - это заджойниться на все возможные таблицы,\nв которых есть свойство `Наименование`. Если в запросе имеется в виду какой-то конкретный\nтип субконто, то можно воспользоваться оператором `Ссылка` следующим образом:\n```\n\tselect * from Документ.ПоступлениеНаРасчетныйСчет where Субконто1 Ссылка Справочник.Контрагенты \n```\nВ этом примере будет сгенерирован только один джойн - с таблицей контрагентов, что существенно быстрее.\n\n* В схеме `simple1c` есть пара функций для работы с Guid-ами. `to_guid` преобразует байтовый массив,\nв котором 1С сохраняет ссылки между объектами, в стандартное строковое представление guid-а.\n`date_from_guid` получает дату из строкового представления guid-а. Так как 1С генерирует guid-ы на основе\nтекущего времени, по этой дате можно судить о том, когда был создан объект с данным идентификатором.\nЭти функции можно использовать в любой части запроса, аналогично стандартным функциям языка запросов 1С.\n\n* Можно получить данные по остаткам и оборотам аналогично стандартному отчету ОСВ в 1С. Для этого\nдоступны четыре таблицы. `РегистрБухгалтерии.Хозрасчетный.Остатки` - здесь лежат помесячные сальдо и обороты без субконто,\n`РегистрБухгалтерии.Хозрасчетный.Субконто1`, `РегистрБухгалтерии.Хозрасчетный.Субконто2`, и\n`РегистрБухгалтерии.Хозрасчетный.Субконто3` - здесь тоже самое, только с субконто.\nКаждая транзакция по счету учитывается в остатках и в одной из таблиц Субконто,\nв зависимости от количества субконт по данному счету.\n\nВот [статья на Хабре](https://habrahabr.ru/company/knopka/blog/314030/) о том, как все это работает.\n\n##Simple1C.COM\n\nНесмотря на то, что еще в 2013-м году 1С опубликовал REST апи\nповерх протокола OData ([раз](https://wonderland.v8.1c.ru/blog/avtomaticheskiy-rest-interfeys-prikladnykh-resheniy),\n[два](https://wonderland.v8.1c.ru/blog/rasshirenie-podderzhki-protokola-odata)),\nмногим и сегодня по разным причинам приходится использовать для интеграции\nстарые COM-интерфейсы. Мы упрощаем использование этих интерфейсов\nза счет автоматической генерации классов по метаданным 1С\nи реализации [LINQ-провайдера](https://msdn.microsoft.com/en-us/library/bb308959.aspx).\nИспользуем C# как основной язык для автогенерации.\nМеханику провайдера упрощаем за счет [вот этой](https://relinq.codeplex.com) классной штуки.\nАналогичные проекты: http://www.linq-demo.1csoftware.com, http://www.vanessa-sharp.ru/reference-linq.html.\nОсновные возможности:\n\n* Автоматическая генерация классов объектной модели по 1С-конфигурации :\n```\nGenerator.exe\n\t-cmd gen-cs-meta\n\t-connection-string File=C:\\my-1c-db;Usr=Администратор;Pwd=\n\t-namespace-root MyNameSpace.ObjectModel1C\n\t-scan-items Документ.СписаниеСРасчетногоСчета\n\t-source-path C:\\sources\\AwesomeSolution\\ObjectModel1CProject\\AutoGenerated\n```\nТакая команда создаст класс СписаниеСРасчетногоСчета в папке Документы.\nЭтот класс будет обладать всеми свойствами исходного 1С-документа\nСписаниеСРасчетногоСчета, включая все табличные части. По классу так же будет создано\nдля каждого из объектов конфигурации, на которые эти свойства\nссылаются (транзитивное замыкание).\nОсновные возможности:\n\n* Для имен генерируемых классов используем исходные русскоязычные идентификаторы из 1С.\nЗа счет этого модель становится проще - нет необходимости придумывать англоязычные\nаналоги для весьма специфических терминов 1С, одни и те же вещи называются одинаково\nпо всей кодовой базе.\n\n* Не навязываем механизм управления коннекциями. Здесь возможны различные варианты\n(ThreadLocal, Pool, пересоздание по таймауту, пересоздание при обрыве и т.п.),\nмногое зависит от приложения и конкретных потребностей. Простейший пример чтобы начать работать:\n\n```csharp\n\tvar connectorType = Type.GetTypeFromProgID(\"V83.COMConnector\");\n\tdynamic connector = Activator.CreateInstance(connectorType);\n\tvar globalContext = connector.Connect(\"File=C:\\my-1c-db;Usr=Администратор;Pwd=\");\n\tvar dataContext = DataContextFactory.CreateCOM(globalContext, typeof(Контрагенты).Assembly);\n\tvar контрагент = new Контрагенты\n\t{\n\t\tИНН = \"1234567890\",\n\t\tНаименование = \"test-counterparty\",\n\t\tЮридическоеФизическоеЛицо = ЮридическоеФизическоеЛицо.ЮридическоеЛицо\n\t};\n\tdataContext.Save(контрагент);\n\tvar контрагент2 = dataContext.Select\u003cКонтрагенты\u003e().Single(x =\u003e x.Код == counterparty.Код);\n\tAssert.That(контрагент2.ИНН, Is.EqualTo(\"1234567890\"));\n```\n\n* Документы и справочники Generator.exe превращает в классы, а перечисления - в enum-ы языка C#.\nВ примере выше для создания контрагента мы используем enum ЮридическоеФизическоеЛицо.\n\n* Абстрагируем ссылки, про них в прикладном коде можно просто\nзабыть - создаем экемпляры классов объектной модели, присваиваем их свойствам других классов,\nпри маппинге на соответствующие COM-объекты ссылки между ними будут проставлены автоматически.\n\n```csharp\n\tvar контрагент = new Контрагенты\n\t{\n\t\tИНН = \"1234567890\",\n\t\tНаименование = \"test-counterparty\",\n\t\tЮридическоеФизическоеЛицо = ЮридическоеФизическоеЛицо.ЮридическоеЛицо\n\t};\n\tdataContext.Save(контрагент);\n\tvar организация = dataContext.Select\u003cОрганизация\u003e().Single();\n\tvar договор = new ДоговорыКонтрагентов\n\t{\n\t\tВидДоговора = ВидыДоговоровКонтрагентов.СПокупателем,\n\t\tНаименование = \"test name\",\n\t\tВладелец = контрагент,\n\t\tОрганизация = организация\n\t};\n\tdataContext.Save(договор);\n```\n\n* Метод Save сохраняет все объекты, до которых может добраться по ссылкам. Пример выше можно\nупростить следующим образом\n\n```\n\tdataContext.Save(new ДоговорыКонтрагентов\n\t{\n\t\tВидДоговора = ВидыДоговоровКонтрагентов.СПокупателем,\n\t\tНаименование = \"test name\",\n\t\tВладелец = new Контрагенты\n\t\t{\n\t\t\tИНН = \"1234567890\",\n\t\t\tНаименование = \"test-counterparty\",\n\t\t\tЮридическоеФизическоеЛицо = ЮридическоеФизическоеЛицо.ЮридическоеЛицо\n\t\t},\n\t\tОрганизация = dataContext.Select\u003cОрганизация\u003e().Single()\n\t});\n```\n\n* В запросах можно использовать стандартные Linq-операторы (Join, GroupBy пока не реализованы)\n\n```csharp\npublic decimal GetCurrencyRateToDate(string currencyCode, DateTime date)\n{\n\treturn dataContext.Select\u003cКурсыВалют\u003e()\n\t\t.Where(x =\u003e x.Валюта.Код == currencyCode)\n\t\t.Where(x =\u003e x.Период \u003c= date)\n\t\t.OrderByDescending(x =\u003e x.Период)\n\t\t.First()\n\t\t.Курс;\n}\n```\n\n* Умеем обновлять отдельные строки табличных частей. Так, например, в таком примере\n\n```csharp\nvar поступлениеТоваровУслуг = new ПоступлениеТоваровУслуг\n{\n\tДата = new DateTime(2016, 6, 1),\n\tКонтрагент = new Контрагенты\n\t{\n\t\tИНН = \"7711223344\",\n\t\tНаименование = \"ООО Тестовый контрагент\",\n\t},\n\tУслуги = new List\u003cПоступлениеТоваровУслуг.ТабличнаяЧастьУслуги\u003e\n\t{\n\t\tnew ПоступлениеТоваровУслуг.ТабличнаяЧастьУслуги\n\t\t{\n\t\t\tНоменклатура = new Номенклатура\n\t\t\t{\n\t\t\t\tНаименование = \"стрижка\"\n\t\t\t},\n\t\t\tКоличество = 10,\n\t\t\tСодержание = \"стрижка с кудряшками\"\n\t\t},\n\t\tnew ПоступлениеТоваровУслуг.ТабличнаяЧастьУслуги\n\t\t{\n\t\t\tНоменклатура = new Номенклатура\n\t\t\t{\n\t\t\t\tНаименование = \"стрижка усов\"\n\t\t\t},\n\t\t\tКоличество = 10,\n\t\t\tСодержание = \"стрижка бороды\"\n\t\t}                \n\t};\ndataContext.Save(поступлениеТоваровУслуг);\nvar t = поступлениеТоваровУслуг.Услуги[0];\nпоступлениеТоваровУслуг.Услуги[0] = поступлениеТоваровУслуг.Услуги[1];\nпоступлениеТоваровУслуг.Услуги[1] = t;\ndataContext.Save(поступлениеТоваровУслуг);\n```\n\nна втором вызове Save будет сгенерирован единственный вызов метода `Сдвинуть`, меняющий\nместами две строки.\n\n* Через метод DataContextFactory.CreateInMemory() можно получить inmemory-реализацию\nинтерфейса IDataContext. Это здорово помогает при автоматизированном тестировании\nбезнес-логики. Весь граф сервисных объектов поверх IDataContext можно создать\nцеликом в inmemory-режиме, значительно ускорив этим прохождение тестов по сравнению\nс работой с настоящей 1С.","funding_links":[],"categories":["Фреймворки для интеграции с 1С"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fivan816%2Fsimple-1c","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fivan816%2Fsimple-1c","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fivan816%2Fsimple-1c/lists"}