Code First и Linq to EF на примере 1С версии 8.3. Часть II

09.09.20

Разработка - Языки и среды

Эта статья - продолжение http://infostart.ru/public/393228/ Там же лежит и обработка для генерации C# файлов. Суть та же, что и для 7.7, но есть особенности.

Здесь лежит практика использования //infostart.ru/public/402433/

Начнем с класса предка.

 

  public   class   СсылочныйТип

    {

 

        [Key]

        [Column("_IDRRef")]

        [MaxLength(16)]

        public  byte[] ID { get; set; }

 

        [NotMapped]

        public  virtual  int  НомерТаблицы { get { return 0; } }

    }

 

Номер таблицы нам понадобится для неопределенных типов.

Кроме того, мы сможем сделать дженерик метод

 

public TEntity ПолучитьСсылочныйЭлемент<TEntity>(byte[] ID) where TEntity : СсылочныйТип

        {

 

 

            var query = from спр in this.Set<TEntity>()

                         where спр.ID == ID

                         select спр;

            return query.SingleOrDefault<TEntity>();

 

        }

 

Пока реализованы справочники, табличные части и перечисления

Это описание Справочника предка

  public  abstract  class  СправочникПредок :СсылочныйТип

    {

     [Column("_Version", TypeName = "timestamp")]

        [MaxLength(8)]

        [Timestamp]

        public byte[] Версия { get; set; }

       

        [Column("_Marked")]

        [Required]

        [MaxLength(1)]

        public byte[] ПометкаУдаленияId { get; set; }

 

        [Column("_PREDEFINEDID")]

        [Required]

        [MaxLength(16)]

        public byte[] ПредопределенныйId { get; set; }

 

        [NotMapped]

        public bool ПометкаУдаления

        {

            get { return ПометкаУдаленияId.ВБулево(); }

 

            set

            {

                ПометкаУдаленияId = value.БулевоВМассив();

            }

        }

 

        public  abstract  string Наименование { get; set; }

        public  abstract  byte[] ЭтоГруппаId { get; set; }

        public  abstract  object ПолучитьКод();

        public  abstract  string Вид();

        public  bool  ЭтоГруппа() { return  ЭтоГруппаId.ВБулево(); }

 

 

    }

 

А Это табличной части

public  partial  class  ТабличнаяЧастьПредок

    {

 

        virtual  public  byte[] СсылкаID { get; set; }

 

        [Key]

        [Column("_KeyField", Order = 1)]

        [MaxLength(4)]

        publicbyte[] KeyField { get; set; }

        virtual  public  int  НомерСтроки { get; set; }

 

 

    }

 

На основании этих предков можно уже создавать потомков

 

Я сделал несколько тестовых справочников со всевозможными типами.

Например

 

[Table("_Reference10")]

public  partial  class  Тестовый:СправочникПредок

{

public  const  int  НомТаблицы=10;

public  const  string  ВидСпр="Тестовый";

[NotMapped]

override  public  byte[] ЭтоГруппаId { get{return КонстантыБД.Ложь;} set{} }

 

[Column("_CODE",TypeName = "nvarchar")]

[Required]

[StringLength(9)]

 public  string  Код { get; set; }

 

[Column("_DESCRIPTION",TypeName = "nvarchar")]

[Required]

[StringLength(25)]

override  public  string  Наименование { get; set; }

 

 

[Column("_Fld12",TypeName = "nvarchar")]

[StringLength(20)]

public  string  Строка { get; set; }

 

[Column("_Fld46",TypeName = "nchar")]

[StringLength(10)]

public  string  СтрокаФиксированная { get; set; }

 

[Column("_Fld47",TypeName = "ntext")]

public  string  СтрокаДлинная { get; set; }

 

[Column("_Fld13",TypeName = "numeric")]

[Required]

public System.Decimal Число { get; set; }

 

[Column("_Fld14",TypeName = "numeric")]

[Required]

public System.Int64 Целое { get; set; }

 

[Column("_Fld15")]

[Required]

public  DateTime  Дата { get; set; }

 

[Column("_Fld16")]

[Required]

[MaxLength(1)]

public  byte[] БулевоId { get; set; }

 

[Column("_Fld17",TypeName = "image")]

[Required]

public  byte[] ХранилищеЗначения { get; set; }

 

[Column("_Fld18")]

[Required]

[MaxLength(16)]

public  byte[] УникальныйИдентификатор { get; set; }

public  НеопределенныеТипы.ЛюбаяСсылка_Fld19 ЛюбаяСсылкаId { get; set; }

 

[Column("_Fld20RRef")]

[Required]

[MaxLength(16)]

public  byte[] ПеречислениеДляТестовId { get; set; }

public  НеопределенныеТипы.РевизитВсеТипы_Fld37 РевизитВсеТипыId { get; set; }

public  НеопределенныеТипы.НеопределенныйНеССылочный_Fld40 НеопределенныйНеССылочныйId { get; set; }

 

[Column("_Fld48RRef")]

[Required]

[MaxLength(16)]

public  byte[] РеквизитСправочникId { get; set; }

 

[Column("_Fld49RRef")]

[Required]

[MaxLength(16)]

public  byte[] РеквизитДокументId { get; set; }

 

override  public string ToString(){returnКод.ToString();}

       [NotMapped]

public  bool  Булево {

   get { return БулевоId.ВБулево(); }

 

 set

   {

  БулевоId = value.БулевоВМассив();

    }

}

       [NotMapped]

public  object  ЛюбаяСсылка { get{return КонстантыБД.ПолучитьЗначениеНеопределенногоТипа(ЛюбаяСсылкаId);} set{КонстантыБД.УстановитьЗначениеНеопределенногоТипа(value,ЛюбаяСсылкаId);} }

virtual  public  Перечисление.ДляТестовСсылка ПеречислениеДляТестов { get; set; }

       [NotMapped]

public  object  РевизитВсеТипы { get{return КонстантыБД.ПолучитьЗначениеНеопределенногоТипа(РевизитВсеТипыId);} set{КонстантыБД.УстановитьЗначениеНеопределенногоТипа(value,РевизитВсеТипыId);} }

       [NotMapped]

public  object  НеопределенныйНеССылочный { get{return КонстантыБД.ПолучитьЗначениеНеопределенногоТипа(НеопределенныйНеССылочныйId);} set{КонстантыБД.УстановитьЗначениеНеопределенногоТипа(value,НеопределенныйНеССылочныйId);} }

virtual  public  Справочник.Номенклатура РеквизитСправочник { get; set; }

[InverseProperty("Владелец")]

publicICollection<Справочник.ПодчиненныйОдинВладелец> ПодчиненныеПодчиненныйОдинВладелец { get; set; }

[InverseProperty("Ссылка")]

publicICollection<ТЧ.ТабЧасть> ПодчиненныеТабЧасть { get; set; }

public  override  int  НомерТаблицы { get { return НомТаблицы; } }

public  override  string  Вид(){return ВидСпр;}

public  override  object  ПолучитьКод(){return Код;}

 

}

 

В отличие от 7.7 здесь введены новые типы для неопределенных типов.

Например

 

[ComplexType]

public  class  РевизитВсеТипы_Fld37:НеопределенныйТип,НеопределенныйТипБулево,НеопределенныйТипЧисло,НеопределенныйТипДата,НеопределенныйТипСтрока,НеопределенныйТипСсылочный

{

[Column("_Fld37_TYPE")]

[Required]

[MaxLength(1)]     

override  public byte[] Тип { get; set; }

 

[Column("_Fld37_L")]

[Required]

[MaxLength(1)]

public byte[] БулевоId { get; set; }

 

[Column("_Fld37_N",TypeName = "numeric")]

[Required]

public  decimal  Число { get; set; }

 

[Column("_Fld37_T")]

[Required]

public  DateTime  Дата { get; set; }

 

[Column("_Fld37_S",TypeName = "nvarchar")]

[StringLength(42)]

public  string  Строка { get; set; }

 

    [Column("_Fld37_RTREF")]

        [Required]

        [MaxLength(4)]

      public  byte[] НомерТаблицы { get; set; }

    

[Column("_Fld37_RRREF")]

       [Required]

        [MaxLength(16)]

        public  byte[] Ссылка { get; set; }

 

       [NotMapped]

public bool Булево {

   get { return БулевоId.ВБулево(); }

 

 set

   {

  БулевоId = value.БулевоВМассив();

    }

}

 

}

 

 

Такие типы помечаются атрибутом [ComplexType]

Что позволяет использовать их так

 

public НеопределенныеТипы.РевизитВсеТипы_Fld37 РевизитВсеТипыId { get; set; }

 

и получение, и установка объекта

[NotMapped]

public  object  РевизитВсеТипы { get{return КонстантыБД.ПолучитьЗначениеНеопределенногоТипа(РевизитВсеТипыId);} set{КонстантыБД.УстановитьЗначениеНеопределенногоТипа(value,РевизитВсеТипыId);} }

 

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

 

public  class  НеопределенныйТип

    {

        virtual  public  byte[] Тип { get; set; }

    }

 

    public  interface  НеопределенныйТипЧисло

    {

        Decimal  Число { get; set; }

    }

 

    public  interface  НеопределенныйТипСтрока

    {

        string  Строка { get; set; }

    }

 

    public  interface  НеопределенныйТипБулево

    {

        bool  Булево { get; set; }

    }

 

    public  interface  НеопределенныйТипДата

    {

        DateTime  Дата { get; set; }

    }

 

    public  interface  НеопределенныйТипСсылочный

    {

        byte[] НомерТаблицы { get; set; }

        byte[] Ссылка { get; set; }

 

    }

 

 

Теперь можно написать методы чтения и установки объектов

 

public  static  object ПолучитьЗначениеНеопределенногоСсылочного(НеопределенныйТип ВладелецId)

        {

            var НТС=ВладелецId as НеопределенныйТипСсылочный;

            Func<byte[], object> значение;

            if (ОбъектыПоТипу.TryGetValue(НТСомерТаблицы.byteArrayToInt(), out значение))

                return значение(НТС.Ссылка);

 

                    return null;

        }

        public  static  object ПолучитьЗначениеНеопределенногоТипа(НеопределенныйТип ВладелецId)

        {

            var тип = ВладелецId.ТипБайт();

 

            switch(тип)

            {

                case 1: return  null;

                case 2: return (ВладелецId as НеопределенныйТипБулево).Булево;

                case 3: return (ВладелецId as НеопределенныйТипЧисло)исло;

                case 4: return (ВладелецId as НеопределенныйТипДата)ата;

                case 5: return (ВладелецId as НеопределенныйТипСтрока)трока;

                case 8: return ПолучитьЗначениеНеопределенногоСсылочного(ВладелецId);

            }

            return  null;

        }

 

 

ОбъектыПоТипу это хэш таблица, которая заполняется так

 

public  partial  class  КонстантыБД

    {

         static КонстантыБД()

        {

            ОбъектыПоТипу = new  Dictionary<int, Func<byte[], object>>();

 

 

ОбъектыПоТипу.Add(Справочник.Тестовый.НомТаблицы,

      (ключ) => { return БДолучитьСсылочныйЭлемент<Справочник.Тестовый>(ключ); }

      );

 

ОбъектыПоТипу.Add(Справочник.Номенклатура.НомТаблицы,

      (ключ) => { return БДолучитьСсылочныйЭлемент<Справочник.Номенклатура>(ключ); }

      );

 

ОбъектыПоТипу.Add(Справочник.ПодчиненныйОдинВладелец.НомТаблицы,

      (ключ) => { return БДолучитьСсылочныйЭлемент<Справочник.ПодчиненныйОдинВладелец>(ключ); }

      );

 

ОбъектыПоТипу.Add(Справочник.ПодчиненныйДваВладельца.НомТаблицы,

      (ключ) => { return БДолучитьСсылочныйЭлемент<Справочник.ПодчиненныйДваВладельца>(ключ); }

      );

 

ОбъектыПоТипу.Add(Справочник.Справочник1.НомТаблицы,

      (ключ) => { return БДолучитьСсылочныйЭлемент<Справочник.Справочник1>(ключ); }

      );

 

 ОбъектыПоТипу.Add(Перечисление.ДляТестовСсылка.НомТаблицы,

                   (ключ) => { var значение = БДолучитьСсылочныйЭлемент<Перечисление.ДляТестовСсылка>(ключ);

                   if (значение == null)

                       retur nnull;

 

                   return значениеначение;

                  

                   }

                   );

 

          

         }

    }

 

 

Ну и реализация установки значений

 

public  static  void УстановитьЗначениеНеопределенногоТипа(object value,НеопределенныйТип ВладелецId)

        {

           

            ОчиститьСтароеЗначениеНеопределенного(ВладелецId);

            if (value==null)

            {

                ВладелецId.Тип[0] =1;

                return;

            }

       

            var тип=value.GetType();

            if (тип==typeof(bool))

            {

                ВладелецId.Тип[0] =2;

                (ВладелецId as  НеопределенныйТипБулево)улево = (bool)value;

 

            }

            elseif (тип == typeof(decimal))

            {

                ВладелецId.Тип[0]=3;

                (ВладелецId as  НеопределенныйТипЧисло).Число = (decimal)value;

 

            }

            elseif (тип == typeof(DateTime))

            {

                ВладелецId.Тип[0] = 4;

                (ВладелецId as  НеопределенныйТипДата).Дата = (DateTime)value;

 

            }

            elseif (тип == typeof(string))

            {

                ВладелецId.Тип[0] =5;

                (ВладелецId as  НеопределенныйТипСтрока).Строка = (string)value;

 

            }

            elseif (value is  СсылочныйТип)

            {

                ВладелецId.Тип[0] = 8;

                varзначение = value as  СсылочныйТип;

               

                var Владелец = ВладелецId as  НеопределенныйТипСсылочный;

                ВладелецомерТаблицы = значение.НомерТаблицы.intToByteArray();

                Владелецсылка = значение.ID;

 

            }

        }

 

 

 

Еще одна особенность это описание перечислений

 

namespace Linq21c8.Перечисление

{

    [Table("_Enum11")]

    public  partial  class  ДляТестовСсылка :СсылочныйТип

    {

        [Column("_ENUMORDER", TypeName = "numeric")]

 

        [Required]

        public  ДляТестов Значение { get; set; }

 

 

        public  const  int  НомТаблицы = 11;

        public  override  int  НомерТаблицы { get { returnНомТаблицы; } }

 

    }

    public  enum  ДляТестов

    {

        Первый // Первый

        , Второй // Второй

    }

    public  static  class  РасширениеПеречисления

    {

 

        public  static  ДляТестовСсылка ПолучитьСсылку(thisДляТестов ID)

        {

            var БД = КонстантыБДД;

            var query = from спр in БДляТестов_Перечисл

                        where  спр.Значение == ID

                        select  спр;

            return query.SingleOrDefault();

        }

 

    }

 

}

Так в CodeFirs числовому значению можно задать тип перечисления

 

        public  ДляТестов  Значение { get; set; }

 

 

Кроме того реализован класс для расширения перечисления

 

Пример использования

 

  var перечисление_Первый = Перечисление.ДляТестов.Первый.ПолучитьСсылку();

 

  var перечисление_Второй = Перечисление.ДляТестов.Второй.ПолучитьСсылку();

 

   foreach (var  спр  in qr2)

  {

    спртрокаФиксированная = "";

    спрелое = ++целое;

 

      if (целое % 2 == 1)

        спреречислениеДляТестов = перечисление_Первый;

       else

        спреречислениеДляТестов = перечисление_Второй;

 

 

     бд.Entry(спр).State = System.Data.Entity.EntityState.Modified;

 

    }

 

Также можно задавать условие

 

var qr2 = from Номенклатура in бдестовый_Спр

 where НоменклатураеречислениеДляТестов.Значение==Перечисление.ДляТестов.Второй

 select Номенклатура;

 

 

Есть особенность для ComplexType

 

   public partial class Тестовый : СправочникПредок

    {

        public partial class НеопределенныеТипы

        {

            [ComplexType]

            public class ЛюбаяСсылка_Fld19 : НеопределенныйТип, НеопределенныйТипСсылочный

            {

                [Column("_Fld19_TYPE")]

                [Required]

                [MaxLength(1)]

                override public byte[] Тип { get; set; }

 

                [Column("_Fld19_RTREF")]

                [Required]

                [MaxLength(4)]

                public byte[] НомерТаблицы { get; set; }

 

                [Column("_Fld19_RRREF")]

                [Required]

                [MaxLength(16)]

                public byte[] Ссылка { get; set; }

 

            }

       }

  }

 

 

public partial class  Тестовый : СправочникПредок

    {

        public partial class  ТЧ

        {

            public partial class  НеопределенныеТипы

            {

                [ComplexType]

                public class  ЛюбаяСсылка_Fld52 : НеопределенныйТип, НеопределенныйТипСсылочный

                {

                    [Column("_Fld52_TYPE")]

                    [Required]

                    [MaxLength(1)]

                    override public byte[] Тип { get; set; }

 

                    [Column("_Fld52_RTREF")]

                    [Required]

                    [MaxLength(4)]

                    public byte[] НомерТаблицы { get; set; }

 

                    [Column("_Fld52_RRREF")]

                    [Required]

                    [MaxLength(16)]

                    public byte[] Ссылка { get; set; }

 

                }

 

            }

 

 

        }

    }



Есть поле в разных типах ЛюбаяСсылка, но в базе все названия [ComplexType] должны быть уникальными.
Поэтому добавляю номер таблицы для неопределенных владельцев и номер поля для неопределенных полей

 

 

Теперь посмотрим на реализацию табличной части

public   partial    class   ТабличнаяЧастьПредок

    {

 

        virtual  public  byte[] СсылкаID { get; set; }

 

        [Key]

        [Column("_KeyField", Order = 1)]

        [MaxLength(4)]

        public byte[] KeyField { get; set; }

        virtual  public  int  НомерСтроки { get; set; }

 

 

    }

 

 

[Table("_Reference10_VT31")]

public  partial  class  ТабЧасть:ТабличнаяЧастьПредок

{

   [Key]

   [Column("_Reference10_IDRRef", Order = 0)]

   [MaxLength(16)]

  override  public byte[] СсылкаID { get; set; }

 

    [Key]

   [Column("_LineNo32", Order = 2, TypeName = "numeric")]

   override  public  int  НомерСтроки { get; set; }

 

[Column("_Fld33RRef")]

[Required]

[MaxLength(16)]

public  byte[] НоменклатураId { get; set; }

 

[Column("_Fld34",TypeName = "numeric")]

[Required]

public System.Int64 Количество { get; set; }

 

[Column("_Fld35",TypeName = "numeric")]

[Required]

public System.Decimal Сумма { get; set; }

public   НеопределенныеТипы.ЛюбаяСсылка_Fld52 ЛюбаяСсылкаId { get; set; }

 

virtual  public  Справочник.Тестовый Ссылка { get; set; }

virtual  public  Справочник.Номенклатура Номенклатура { get; set; }

       [NotMapped]

public  object  ЛюбаяСсылка { get{returnКонстантыБД.ПолучитьЗначениеНеопределенногоТипа(ЛюбаяСсылкаId);} set{КонстантыБД.УстановитьЗначениеНеопределенногоТипа(value,ЛюбаяСсылкаId);} }

 

}

 

 

Так, в ТЧ три ключевых поля СсылкаID, KeyField и НомерСтроки

Ссылка это владелец табличной части.

 

Основной метод, создающий описание полей, выглядит так

 

Процедура ПрописатьРеквизит(тип,ИмяСвойства,ПолеБД,Реквизит,ТекстПолей, ТекстВиртуальных,ТипВладельца)
    ИмяРеквизита=ИмяСвойства;
    СтрВиртуал="";
    Required="
    |[Required]";
    Стр="";
    TypeName="";
    Если Тип=Тип("Булево") Тогда
        Стр=  "[MaxLength(1)]";
        ИмяРеквизита=ИмяСвойства+"Id";
        ТипРеквизита= "byte[]";
        СтрВиртуал= СоздатьВиртуальноеБулево(ИмяСвойства);



    ИначеЕсли Тип=Тип("Число") Тогда
        TypeName="numeric";
        ТипРеквизита=  ПолучитьТипЧисла(Реквизит.Тип);

    ИначеЕсли Тип=Тип("Дата") Тогда

        ТипРеквизита=  "DateTime";


    ИначеЕсли Тип=Тип("Строка") Тогда

        КвалификаторыСтроки=Реквизит.Тип.КвалификаторыСтроки;

        ДлинаСтроки=  КвалификаторыСтроки.Длина;
        Стр=  "[StringLength("+ДлинаСтроки+")]";
        Если ДлинаСтроки=0 Тогда

            TypeName="ntext";
            Required="";
            Стр= "";
        ИначеЕсли КвалификаторыСтроки.ДопустимаяДлина=ДопустимаяДлина.Фиксированная Тогда
            TypeName="nchar";
            Required="";


        Иначе
            Required="";
            TypeName="nvarchar";
        КонецЕсли;



        ТипРеквизита=  "string";

    ИначеЕсли Тип=Тип("ХранилищеЗначения") Тогда
        TypeName= "image";
        ТипРеквизита= "byte[]";

    ИначеЕсли Тип=Тип("УникальныйИдентификатор") Тогда
        Стр=  "[MaxLength(16)]";
        ТипРеквизита= "byte[]";
    ИначеЕсли  Справочники.ТипВсеСсылки().СодержитТип(Тип) Тогда
        ИмяРеквизита=ИмяСвойства+"Id";
        стр="[MaxLength(16)]";
        ТипРеквизита= "byte[]";
        Вид=Метаданные.НайтиПоТипу(Тип).Имя;
        ТипВид=Метаданные.НайтиПоТипу(Тип).ПолноеИмя();
        СтрВиртуал="virtual public Справочник."+Вид+" "+ИмяСвойства+" { get; set; }";
        // Когда вид реквизита видом самого справочника добавим коллекцию на подчиненные элементы
        Если ТипВид=ТипВладельцаТогда
            СтрВиртуал=СтрВиртуал+"
            |[InverseProperty("""+ИмяСвойства+""")]
            |public ICollection<Справочник."+Вид+"> ПодчиненныеДля"+ИмяСвойства+" { get; set; }";

        КонецЕсли;
    ИначеЕсли  Перечисления.ТипВсеСсылки().СодержитТип(Тип) Тогда
        ИмяРеквизита=ИмяСвойства+"Id";
        стр="[MaxLength(16)]";
        ТипРеквизита= "byte[]";
        Вид=Метаданные.НайтиПоТипу(Тип).Имя;
        СтрВиртуал="virtual public Перечисление."+Вид+"Ссылка "+ИмяСвойства+" { get; set; }";

    Иначе
        // Ссылочный тип Который пока не реализован
        ИмяРеквизита=ИмяСвойства+"Id";
        ТипВид=Метаданные.НайтиПоТипу(Тип).ПолноеИмя();
        стр="[MaxLength(16)]";
        ТипРеквизита= "byte[]";
        Вид=Метаданные.НайтиПоТипу(Тип).Имя;
        //  СтрВиртуал="virtual public "+ТипВид+" "+ИмяСвойства+" { get; set; }";

    КонецЕсли;

    Если TypeName<>"" Тогда
        Стр1=  "[Column("""+ПолеБД+""",TypeName = """+TypeName+""")]";

    Иначе
        Стр1=  "[Column("""+ПолеБД+""")]";



    КонецЕсли;
    Если Стр<>""  Тогда

        Стр="
        |"+Стр;

    КонецЕсли;

    Стр=Стр1+Required+стр+"
    |public "+ТипРеквизита+" "+ИмяРеквизита+" { get; set; }";


    ТекстПолей.ДобавитьСтроку("");
    ТекстПолей.ДобавитьСтроку(Стр);
    Если СтрВиртуал<>"" Тогда

        ТекстВиртуальных.ДобавитьСтроку(СтрВиртуал);

    КонецЕсли;


КонецПроцедуры



Процедура ДобавитьВиртНеопред(ИмяСвойства,Текст)

Стр="   [NotMapped]
|public object %1 { get{return КонстантыБД.ПолучитьЗначениеНеопределенногоТипа(%1Id);} set{КонстантыБД.УстановитьЗначениеНеопределенногоТипа(value,%1Id);} }";

Текст.ДобавитьСтроку(СтрШаблон(Стр,ИмяСвойства));

КонецПроцедуры

Функция ПрописьРеквизитовПоКоллекции(ТипВладельца,Коллекция,Поля,ТекстПолей,ТекстВиртуальных,ТекстНеопределенныхТипов)
    Перем ИмяКлассаНТ;

    Для каждого Реквизит Из Коллекция Цикл
        ИмяРеквизита= Реквизит.Имя;
        ПолеБД=ПолучитьПолеБД(Поля,ИмяРеквизита);
        Сообщить("ИмяРеквизита="+ИмяРеквизита+"  ПолеБД="+ПолеБД);
        Типы=Реквизит.Тип.Типы();
        Если Типы.Количество()=1 Тогда
            Тип=Типы[0];

            ПрописатьРеквизит(тип,ИмяРеквизита,ПолеБД,Реквизит,ТекстПолей, ТекстВиртуальных,ТипВладельца)

        Иначе
            СоздатьНеопределенныйТип(ИмяРеквизита,ПолеБД,Реквизит.Тип,ТипВладельца,ТекстНеопределенныхТипов,ИмяКлассаНТ);
            ТекстПолей.ДобавитьСтроку("public НеопределенныеТипы."+ИмяКлассаНТ+" "+ИмяРеквизита+"Id { get; set; }");
             ДобавитьВиртНеопред(ИмяРеквизита,ТекстВиртуальных);


        КонецЕсли;


    КонецЦикла;


КонецФункции

 

 

 

Также добавлен класс расширения для работы с УИД 1С и byte[]

 

publicstaticclassРасширениеДляГуид

    {

        public  static  string  ВСтроку16(this  byte[] bytes)

        {

            char[] c = new  char[bytes.Length * 2];

 

            byte b;

 

            for (int bx = 0, cx = 0; bx < bytes.Length; ++bx, ++cx)

            {

                b = ((byte)(bytes[bx] >> 4));

                c[cx] = (char)(b > 9 ? b - 10 + 'A' : b + '0');

 

                b = ((byte)(bytes[bx] & 0x0F));

                c[++cx] = (char)(b > 9 ? b - 10 + 'A' : b + '0');

            }

 

            return  new  string(c);

        }

 

        public  static  string  УИд1С(thisbyte[] ДанныеБД)

        {

            varстр = ДанныеБД.ВСтроку16();

 

            varч1 = стр.Substring(24, 8);

            varч2 = стр.Substring(20, 4);

            varч3 = стр.Substring(16, 4);

            varч4 = стр.Substring(0, 4);

            varч5 = стр.Substring(4, 12);

            return (ч1 + "-" + ч2 + "-" + ч3 + "-" + ч4 + "-" + ч5);

        }

 

        public  static  Byte[] Строка16ВМассив(this  string str)

        {

            var res = new  byte[str.Length / 2];

 

            for (int i = 0; i < res.Length; i++)

                res[i] = Convert.ToByte(str.Substring(i * 2, 2), 16);

 

            return res;

        }

        public  static  Byte[] ПолучитьМассивПоУИд(this  string UUID)

        {

            varч1 = UUID.Substring(19, 4);

            varч2 = UUID.Substring(24, 12);

            varч3 = UUID.Substring(14, 4);

            varч4 = UUID.Substring(9, 4);

            varч5 = UUID.Substring(0, 8);

            var str = ч1 + ч2 + ч3 + ч4 + ч5;

 

            return  Строка16ВМассив(str);

 

 

        }

 

 

 

 

 

    }

 

    public  static  class  Converter

    {

 

        public static byte[] ВLittleEndian(this  byte[] ДанныеИзБд)

        {

            var res = new  byte[ДанныеИзБд.Length];

 

            for (var i = 0; i < ДанныеИзБд.Length; i++)

                res[res.Length - 1 - i] = ДанныеИзБд[i];

 

            return res;

        }

        public  static  int byteArrayToInt(this  byte[] ДанныеИзБд)

        {

 

            byte[] данные;

            if (BitConverter.IsLittleEndian)

                данные = ДанныеИзБдLittleEndian();

            else

                данные = ДанныеИзБд;

 

            return  BitConverter.ToInt32(данные, 0);

        }

 

        public  static  byte[] intToByteArray(this  int  значение)

        {

 

            var res = BitConverter.GetBytes(значение);

            if (BitConverter.IsLittleEndian)

                Array.Reverse(res);

 

            return res;

        }

 

        public  static  byte ВБайт(this  byte[] ДанныеИзБд)

        {

 

            return  ДанныеИзБд[0];

        }

 

 

        public  static  byte[] БайтВмассив(this  byteданные)

        {

 

            return  new  byte[] { данные };

        }

 

        public  static  byte[] БулевоВМассив(this  boolданные)

        {

 

            return BitConverter.GetBytes(данные);

        }

 

        public  static  bool  ВБулево(this  byte[] ДанныеИзБд)

        {

 

            return  BitConverter.ToBoolean(ДанныеИзБд, 0);

        }

    }

Code First Linq

См. также

Языки и среды Программист Платформа 1С v8.3 Бесплатно (free)

Будем писать свои скрипты на питоне и запускать их на 1С.

15.04.2024    3541    YA_418728146    13    

62

Мобильная разработка Языки и среды 1С:Элемент Программист Бесплатно (free)

Flutter может быть использован с 1С:Предприятием для разработки кроссплатформенных мобильных приложений, обеспечивая единый интерфейс и функциональность на устройствах под управлением iOS и Android. Это позволяет создавать приложения с высокой производительностью благодаря использованию собственного движка рендеринга Flutter. Интеграция Flutter с 1С:Предприятием позволяет создавать мобильные приложения любого уровня сложности, интегрировать их в корпоративные информационные системы, а также реализовывать бизнес-логику

19.03.2024    16050    ROk_dev    69    

43

Языки и среды Программист Стажер Платформа 1С v8.3 Бесплатно (free)

Существует множество языков программирования, и каждый имеет свои особенности по работе с типами данных. Слабые, явные, динамические и другие... Но кто же здесь 1С и почему с приходом "строгой" типизации EDT 1С-программистам стоит задуматься над изменением своих привычек.

16.01.2024    6705    SeiOkami    22    

61

Языки и среды Программист Бесплатно (free)

Пример небольшого приложения, с которого можно начать изучать язык программирования Dart.

08.08.2023    4031    acvatoris    6    

15

Языки и среды Программист Платформа 1С v8.3 Россия Бесплатно (free)

Написание статического анализатора для 1С традиционным способом на Си.

30.06.2023    3423    prohorp    15    

12

Языки и среды Программист Абонемент ($m)

Поставили нам задачу - вынести на отдельный сервер функционал получения заказов от клиентов по электронной почте, парсинг полученных XLS в приемлемый вид и трансформация заказов в красивый JSON, понятный нашей учетной системе на 1С. Всю эту красоту желательно запустить в отдельном докер - контейнере, по возможности не тратя лицензии, поэтому отдельно стоящую конфигурацию на БСП отвергаем сразу. Можно было бы собрать всё на Apache Airflow или Apache NiFi, но решили попробовать реализовать всю логику без Open Source, будем делать свой ETL, с Исполнителем, который в версии 3.0 научился взаимодействовать с электронной почтой по IMAP. Начнем с середины - сначала напишем скрипты, а потом соберем их в рабочую конструкцию

1 стартмани

01.06.2023    2249    0    kembrik    2    

7

Языки и среды Программист Платформа 1С v8.3 Бесплатно (free)

При работе с 1С ORM (object relation mapping) все время преследует ощущение постоянного создания монолитного приложения — один раз привязался к какой либо сущности (например, справочник Контрагенты), и весь код заполнен ссылками на эту конкретную реализацию. Можно ли независимо разрабатывать в ORM совместимые между собой справочник «Контрагентов» и использующий его документ «Платежное поручение», но при этом избежать жестких зависимостей? Спасут ли нас микросервисы? Пример на аннотациях Java демонстрирует, как это возможно делать.

13.03.2023    1257    1CUnlimited    0    

3
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. WKBAPKA 215 25.09.15 09:02 Сейчас в теме
тысяча чертей! что это?
LeXXeR; dmalyshev; Silenser; michmich; Yakud3a; pbazeliuk; Andreyyy; Andrefan; ya.Avoronov; kasper076; +10 Ответить
3. RomanRomans 28.09.15 21:31 Сейчас в теме
4. Serginio 942 29.09.15 14:18 Сейчас в теме
(3) Да нет все очень прозрачно и понятно. Просто нужно уметь готовить
5. baracuda 2 06.10.15 15:30 Сейчас в теме
(4) Для описания формирования классов добавляется в проект как ссылка на публикуемый интерфейс ODATA в SERVICE REFERENCE?
6. Serginio 942 06.10.15 16:55 Сейчас в теме
Нет. Для этого в части I есть обработка которая формирует модули
http://infostart.ru/public/393228/
7. утюгчеловек 40 08.05.16 22:38 Сейчас в теме
Очень круто.

Но есть пожелание: как-нибудь формулировать в аннотации статьи решаемую задачу.
А то получается что статья про использование технологии, но ни слова о том зачем это нужно, решая какую задачу автору пришлось изучить технологию.
Я, например, нашел статью по ключевым словам. Но ведь есть и те, кто просто набрел сюда случайно.
Linq to 1C ради Linq to 1C, получается.

И кстати ни в одной из статей серии нет выводов.
8. Serginio 942 09.05.16 08:51 Сейчас в теме
Прежде всего это нужно для интеграции с другими программами. В том числе и Asp.Net. Если в 8.x есть вэб,HTTP сервисы,ODATA. То в 7 ке грустно. COM медленный. И главное это скорость выполнения и программирования
Оставьте свое сообщение