Linq to ODATA

1С сейчас совершенствует REST интерфейс приложения, автоматически генерируемый платформой, и протокол обмена ODATA версии 3.
С недавнего времени появилась возможность обмениваться, используя JSON. На просторах интернета мало информации по использованию Linq для ODATA для 1С.
Поэтому решил поделиться опытом. Это продолжение статей https://infostart.ru/public/402433/

ODATA это открытый веб-протокол для запроса и обновления данных. Он позволяет оперировать данными, используя в качестве запросов HTTP-команды.

 

http://v8.1c.ru/o7/201312rest/

Есть поддержка JSON

http://v8.1c.ru/o7/201410json/index.htm

 

Хорошая статья по публикации находится здесь

//infostart.ru/public/305854/index.php?back&vote_id=245&rate=1&ID=305854%3Frate%3D1&bxajaxid=2da474348dcf168272d247336e249b99 

Для того, что бы редактировать состав  стандартного интерфейса можно воспользоваться обработкой

//infostart.ru/public/297325/

Или программно установить используя метод УстановитьСоставСтандартногоИнтерфейсаOData

Массив = Новый Массив();

Для Каждого Справочник Из Метаданные.Справочники Цикл
   
Массив.Добавить(Справочник);
КонецЦикла;

УстановитьСоставСтандартногоИнтерфейсаOData(Массив);

 

Затем в VS Добавить ссылку на службу используя URI

http://{АдресВебСервера}/{ИмяПубликации}/odata/standard.odata/$metadata

Получаем описание классов доступ и доступ к ODATA например так

var uriString = @»http://localhost/LinqBD/odata/standard.odata/»;

            var context = new ServiceReference1.EnterpriseV8(new Uri(uriString));

 

            context.Format.UseJson();

            var query = context.CreateQuery<ServiceReference1.Catalog_Тестовый>(@»Catalog_Тестовый«)

 

если не использовать context.Format.UseJson() то данные будут присылаться в формате XML

Можно получить один элемент по ключу

var query = context.CreateQuery<ServiceReference1.Catalog_Тестовый>(@»Catalog_Тестовый(guid’aada18ad-5308-11e5-8e05-c86000c70663′)»);

Можно добавлять фильтры например

 

var query = context.CreateQuery<ServiceReference1.Catalog_Тестовый>(Catalog_Тестовый«)

                         .AddQueryOption(«$filter«, «Число le 100″);

 

Но проще использовать доступ к ODATA через Linq. Например

 

var result = (from Тестовый in context.Catalog_Тестовый

                          where Тестовый.Число < 500

                          select Тестовый).ToList();

 

var result = (from Тестовый in context.Catalog_Тестовый

                          where Тестовый.Ref_Key == new Guid(«aada18ad-5308-11e5-8e05-c86000c70663»)

                          select Тестовый).SingleOrDefault();

 

То есть можно работать с ODATA полностью на Linq

 Подгрузка ссылочных реквизитов

https://msdn.microsoft.com/ru-ru/library/cc646508(v=vs.110).aspx

var ПустаяСсылка = new Guid(«00000000 — 0000 — 0000 — 0000 — 000000000000»);

 

            string НоменклатураНаименование = «»;

            if (result.РеквизитСправочник_Key != ПустаяСсылка)

            {

                context.LoadProperty(result, «РеквизитСправочник«);

 

               НоменклатураНаименование = result.РеквизитСправочник.Description;

            }

 

Для Неопределенных типов Можно создать функцию

object ПолучитьНеопределенныйТип(ServiceReference1.EnterpriseV8 context, string значение, string Тип)

        {

            switch (Тип)

            {

                case «StandardODATA.Undefined«:

                    return null;

                case «StandardODATA.Catalog_Номенклатура«: return context.Catalog_Номенклатура.Where(Тестовый => Тестовый.Ref_Key == new Guid(значение)).SingleOrDefault();

                case «Edm.Double«: return Double.Parse(значение, System.Globalization.CultureInfo.InvariantCulture);

…..

            }

            return null;

        }

 

Ииспользовать

  dynamic    ЛюбаяССылка = ПолучитьНеопределенныйТип(context, result.ЛюбаяСсылка, result.ЛюбаяСсылка_Type);

     dynamic НеСсылочный = ПолучитьНеопределенныйТип(context, result.НеопределенныйНеССылочный, result.НеопределенныйНеССылочный_Type);

 

 По сути некая замена COM.

 

Полезные ссылки для запросов ODATA

https://msdn.microsoft.com/ru-ru/library/vstudio/dd673933(v=vs.100).aspx

 

Обновление, добавление и удаление записей

 https://msdn.microsoft.com/ru-ru/library/vstudio/dd756361(v=vs.100).aspx

11 Comments

  1. baracuda

    Глоток свежего воздуха при изучении C# Odata.

    Reply
  2. Serginio

    Спасибо!

    Reply
  3. avz_1C

    Коллега, Вы продолжаете удивлять.

    Спасибо.

    Сегодня, как раз, возникла потребность разбирать метаданные нескольких

    конфигураций, взаимодействием которых управляет модуль, созданный на C#.

    Не успел подумать о Linq, как Вы подтвердили, своей публикацией, мои догадки.

    Reply
  4. Serginio

    Спасибо. Рад, что мои труды не пропадают зря

    Reply
  5. TeMochkiN

    Здравствуйте!

    Помогите, пожалуйста, пытаюсь добавить ссылку на службу в VS, а она постоянно запрашивает учетные данные и не дает её добавить:



    Я ввожу имя пользователя, жму ОК, и снова появляется это же окно ввода имени пользователя и пароля.



    После нескольких попыток, жму отмена и пишет следующее:



    Я пробовал открыть данную ссылку в хроме он тоже запрашивает имя пользователя и пароль, я ввожу имя пользователя и всё загружается:

    А вот Internet Explorer тоже не дает открыть эту ссылку. В чем может быть дело? IIS неправильно настроен?

    Reply
  6. Serginio

    Логин и пароль должны быть на латинице

    Reply
  7. Serginio
    Reply
  8. Serginio

    К сожалению VS их не подгружает. Но можно использовать CreateQuery. Но есть нюансы. Если сделать такой запрос

    var query3 = context.CreateQuery<StandardODATA.AccountingRegister_Хозрасчетный_Turnover>(@»AccountingRegister_Хозрасчетный/Turnovers»).ToList();
    

    То 1С вернет такй тип

    {

    «odata.metadata»: «http://localhost/DemoAccounting/odata/standard.odata/$metadata#Collection(StandardODATA.AccountingRegister_Хозрасчетный_Turnover)»;,

    «value»: [

    Для того, что бы программа поняла ответ нужно сделать такой запрос и программа не может привести Collection(StandardODATA.AccountingRegister_Хозрасчетный_Turnover)» к AccountingRegister_Хозрасчетный_Turnover

    Поэтому создадим такой запрос

    var query3 = context.CreateQuery<List<StandardODATA.AccountingRegister_Хозрасчетный_Turnover>>(@»AccountingRegister_Хозрасчетный/Turnovers»).ToList();
    

    То возвращается тип

    query3 Count = 1 System.Collections.Generic.List<System.Collections.Generic.List<StandardODATA.AccountingRegister_Хозрасчетный_Turnover>>

    Где вся коллекция лежит в первом элементе query3.Items[0]

    Reply
  9. Serginio
  10. user895038

    Правильно ли я понимаю, что через ODATA я могу получить только примитивные данные, хоть и используя фильтрацию.

    Т.е. я не могу увидеть в номенклатуре родителя — только ссылку на него, а чтобы узнать Наименование родителя мне нужно выполнить следующий запрос, используя ранее полученный Guid?

    А также, я не могу получить результат запроса к двум соединенным таблицам? Мне надо сначала отфильтровать первую таблицу, запомнить список данных связанного поля, а следующим запросом получить уже данные второй таблицы, послав в запросе весь запомненный список.

    И уже только на клиенте я могу соединить две полученные таблицы.

    Если это не устриавает, то надо использовать преднастроенные WS ссылки и SOAP

    Reply
  11. ture

    Odata это ведь стандарт такой?

    Ну так и что же этому стандарту не соответствует всеми «любимая» 1С?

    И так во всем, кстати.

    Reply

Leave a Comment

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