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

Публикация № 402038

Разработка - Практика программирования

Code First Linq

Эта статья - продолжение 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);

        }

    }

Специальные предложения

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

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

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

См. также

Использование программных перечислений, ч.1: строковые константы Промо

Практика программирования v8 1cv8.cf Бесплатно (free)

Часто ли у вас возникает необходимость в коде выполнять сравнение на строку?

10.12.2016    37562    unichkin    74    

Работа с журналом регистрации. Выходим за границы платформы

Журнал регистрации Бесплатно (free)

Работа с журналом регистрации нестандартными средствами. А также немного про использование платформы .NET в экосистеме 1С.

12.05.2020    6015    YPermitin    24    

Программная работа с настройками СКД

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Нюансы программной работы с настройками системы компоновки данных в отчетах и динамических списках. Обзор всех видов настроек компоновки. Что в каких случаях правильно применять. В качестве примера рассмотрена работа с отборами и группировками.

27.01.2020    27915    ids79    26    

[СКД] Программное создание схемы компоновки данных

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Сделаем отчет на СКД полностью программно, без использования макета "схема компоновки данных".

15.01.2020    24614    John_d    22    

Вспомогательные инструкции в коде 1С Промо

Практика программирования v8 1cv8.cf Бесплатно (free)

Помогаем редактору кода 1С помогать нам писать и анализировать код.

15.10.2018    30543    tormozit    100    

Последовательности событий при проведении документа 1С. Шпаргалка + про формы + про расширения

Практика программирования v8 Россия Бесплатно (free)

Собрал информацию о событиях/подписках/расширениях в одном месте.

30.12.2019    18963    kuzyara    33    

30 задач. Странных и не очень

Практика программирования v8 Бесплатно (free)

30 задач на знание языка программирования 1С и некоторого поведения платформы. Маленьких. Странных и не очень.

02.12.2019    17244    YPermitin    72    

Как передать IP адрес, который вызвал HTTP запрос в 1C (для веб-сервера Apache)

Практика программирования v8 Бесплатно (free)

Столкнулся с задачей получения IP адреса, который вызывает http сервис 1С. Итак, решение:

22.11.2019    8571    Sibars    19    

Оформление и рефакторинг сложных логических выражений Промо

Практика программирования v8 Россия Бесплатно (free)

В сложных логических выражениях нередко самому автору спустя какое-то время тяжело разобраться, не говоря уже о других программистах. Предлагаемая методика позволяет повысить наглядность таких выражений путем оформления в виде И-ИЛИ дерева и одновременно выполнять их рефакторинг.

20.09.2012    78201    tormozit    131    

Таблица значений. Нюансы

Практика программирования v8 Бесплатно (free)

Обзор некоторых аспектов использования общеизвестного инструмента 1С.

01.10.2019    34075    Yashazz    50    

О программе Postman для тестирования API и для чего она нужна 1С-нику

Практика программирования Программное обеспечение (software) v8 Бесплатно (free)

Для чего нужна программа Postman для тестирования API и какая от него польза для 1С-программиста.

24.09.2019    12198    budidich    28    

[Шпаргалка] Программное создание элементов формы

Практика программирования Работа с интерфейсом v8 1cv8.cf Бесплатно (free)

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

06.09.2019    51770    rpgshnik    63    

Запись значения в поле ввода/формы со срабатыванием события ПриИзменении Промо

Практика программирования v8 1cv8.cf Россия Бесплатно (free)

Иногда возникает необходимость после записи значения в какое либо поле ввода/формы вызвать для него обработчик события ПриИзменении, а о вызове самого события приходится только мечтать. В этой статье приводится программный способ вызова этого события.

11.07.2007    48675    tormozit    41    

Агрегатные функции СКД, о которых мало кто знает

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Пользуетесь ли Вы всеми возможными агрегатными функциями, которые предоставляет система компоновки данных? Если Вы используете только: СУММА, КОЛИЧЕСТВО, МИНИМУМ, МАКСИМУМ, СРЕДНЕЕ, то эта статья для Вас.

05.09.2019    50439    ids79    54    

Регистры бухгалтерии. Общая информация

Практика программирования Математика и алгоритмы v8 v8::БУ БУ Бесплатно (free)

Общая информация о внутреннем устройстве регистров бухгалтерии.

05.09.2019    29061    YPermitin    24    

Три костыля. Сказ про фокусы в коде

Практика программирования v8 Бесплатно (free)

Три интересных (или странных) костыля в коде, которые могут помочь в повседневных и не очень задачах.

03.09.2019    25723    YPermitin    80    

Как сделать из &НаКлиентеНаСервереБезКонтекста почти &НаКлиентеНаСервере Промо

Практика программирования v8 1cv8.cf Россия Бесплатно (free)

Как сделать метод формы, доступный на клиенте и на сервере одновременно, и сохранить при этом удобство разработки

10.09.2017    45017    tormozit    74    

Отслеживание выполнения фонового задания

Практика программирования Универсальные функции Разработка v8 1cv8.cf Бесплатно (free)

Запуск фонового задания из модуля внешней обработки. Отслеживание выполнения задания в виде прогресса, расположенного на форме.

17.08.2019    31835    ids79    16    

Функции СКД: ВычислитьВыражение, ВычислитьВыражениеСГруппировкойМассив

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Подробное описание и использование внутренних функций системы компоновки данных: Вычислить, ВычислитьВыражение, ВычислитьВыражениеСГруппировкойМассив, ВычислитьВыражениеСГруппировкойТаблицаЗначений.

08.08.2019    85221    ids79    49    

Фоновое выполнение кода в 1С - это просто

Практика программирования v8 1cv8.cf Бесплатно (free)

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

02.08.2019    36456    avalakh    22    

Выгрузка документа по условию Промо

Практика программирования Разработка v8 Бесплатно (free)

Что делать, если документы нужно выгружать не все подряд, а по какому-то фильтру: статусу, дате, набору условий... А что если он соответствовал этим условиям, а потом перестал? А если потом опять начал? Такие ситуации заставили попотеть не одного программиста.

25.04.2019    16120    m-rv    2    

Разбираемся с параметрами редактирования СКД

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Связь по типу, Параметры выбора, Связи параметров выбора

31.07.2019    24511    json    13    

СКД - наборы данных и связи между ними, создание собственной иерархии, вложенные отчеты

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Набор данных объект. Использование в схеме компоновки нескольких наборов данных. Различные варианты связи наборов: объединение, соединение. Использование иерархии в отчетах на СКД. Создание собственной иерархии, иерархия детальных записей. Использование вложенных схем в отчетах на СКД.

26.07.2019    61572    ids79    11    

СКД - использование расширений языка запросов, секция ХАРАКТЕРИСТИКИ

Инструментарий разработчика Практика программирования v8 v8::СКД Бесплатно (free)

Автоматическое и не автоматическое заполнение полей компоновки данных. Использование расширений языка запросов для СКД «{…}», секция ВЫБРАТЬ, секция ГДЕ, параметры виртуальных таблиц. Автоматизированное использование дополнительных данных в запросе: секция ХАРАКТЕРИСТИКИ.

17.07.2019    36322    ids79    27    

Как прикрутить ГУИД к регистру сведений Промо

Практика программирования Перенос данных из 1C8 в 1C8 Разработка v8 Бесплатно (free)

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

16.04.2019    20371    m-rv    17    

Регистры сведений. За кулисами

Практика программирования Разработка v8 1cv8.cf Бесплатно (free)

Небольшие заметки по внутреннему устройству регистров сведений.

09.07.2019    26338    YPermitin    14    

"Меньше копипаста!", или как Вася универсальную процедуру писал

Практика программирования Разработка v8 v8::СКД 1cv8.cf Бесплатно (free)

Программист Вася разбирает подход создания универсальных методов на примере программного вывода СКД.

04.07.2019    19782    SeiOkami    50    

Работа с настройками системы компоновки данных

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Варианты отчетов, работа с настройками вариантов: структура группировок, поля отчета, отборы, сортировка, условное оформление, другие настройки, настройки отображения диаграмм.

02.07.2019    48047    ids79    17    

Как сделать запрос на изменение данных Промо

Практика программирования v8 v8::Запросы 1cv8.cf Бесплатно (free)

В статье приведены особенности внутренней архитектуры и примеры работы с расширением языка запросов 1С.

01.06.2018    30854    m-rv    21    

Создание отчетов с помощью СКД - основные понятия и элементы

Практика программирования Математика и алгоритмы v8 v8::СКД Бесплатно (free)

Основные принципы работы СКД. Понятия схемы компоновки и макета компоновки. Описание основных элементов схемы компоновки: наборы данных, поля, вычисляемые поля, ресурсы, параметры.

25.06.2019    53549    ids79    25    

Многопоточное ускорение однопользовательских нагрузок в 1С + Microsoft SQL Server 2017

Практика программирования Производительность и оптимизация (HighLoad) v8 v8::Запросы Бесплатно (free)

Взаимодействие с Microsoft SQL Server нередко вызывает трудности у 1С-ников, а потому интересны любые моменты, связанные с его использованием. О своем опыте работы с новым SQL Server 2017 участникам конференции Infostart-2018 рассказал директор ООО «Аналитика софт» Дмитрий Дудин.

11.06.2019    25368    dmurk    145    

Регистры накопления. Структура хранения в базе данных

Практика программирования Разработка v8 1cv8.cf Бесплатно (free)

Структура хранения регистров накопления в базе данных для платформы 1С:Предприятие 8.x. Первая часть в серии публикаций.

16.05.2019    43914    YPermitin    30    

Метод формирования движений в типовых регистрах нетиповыми регистраторами Промо

Практика программирования v8 1cv8.cf Бесплатно (free)

Вариант решения задач с проведением по типовым регистрам нетиповыми регистраторами. Зачем - чтобы при сравнении конфигурации не обращать внимание на свойства регистров и исключить вероятность допущения горькой оплошности при обновлении информационных баз, заменив типы регистраторов основной конфигурации типами конфигурации поставщика. Для программных продуктов, имеющих в своем составе метаданных документ "Корректировка регистров"("Корректировка записей регистров").

05.12.2017    28348    itriot11    34    

О расширениях замолвите слово...

Практика программирования Разработка v8 Бесплатно (free)

О чём стоит задуматься при принятии решения о создании расширения конфигурации…

07.04.2019    35710    ellavs    126    

Git-репозитории для 1С-кода (опыт использования при небольших проектах)

Практика программирования v8 Бесплатно (free)

Инструкции по взаимодействию с Git-репозиторием, которые писались для тех наших программистов, которые вообще никогда не работали с Git (руководства в духе "Как получить код из git-репозитория?", "Как отправить код в git-репозиторий")...

28.03.2019    27586    ellavs    90    

Трюки с внешними источниками данных

Практика программирования Разработка v8 1cv8.cf Бесплатно (free)

Некоторые трюки для преодоления ограничений внешних источников данных.

14.03.2019    31667    YPermitin    53    

Использование классов .Net в 1С для новичков Промо

Практика программирования Разработка внешних компонент Универсальные функции v7.7 v8 Бесплатно (free)

Руководство для новичков. Написав статью http://infostart.ru/public/238584/, я понял, что многие не понимают того, что написано. Поэтому в этой статье постараюсь более подробно остановиться на азах и без кода на вражеском языке (C#)

27.01.2016    76675    Serginio    108    

Ошибки при работе с хранилищем конфигурации и способы их решения

Практика программирования v8 Бесплатно (free)

В статье собраны наиболее распространенные ошибки при работе с хранилищем конфигурации и способы их обхода и решения.

01.03.2019    40260    Смешной 1С    28    

Разработка и сценарное тестирование с Vanessa-ADD. Отчетность Allure. Автоматизация запуска сценариев

Практика программирования Vanessa Automation v8 Россия Бесплатно (free)

Формируем отчетность о результатах выполнения сценариев. Автоматизируем запуск.

26.02.2019    22361    Vladimir Litvinenko    27    

Автоматические и управляемые блокировки применительно к типовым конфигурациям 1С Промо

Математика и алгоритмы Практика программирования v8 v8::blocking 1cv8.cf Бесплатно (free)

Основные принципы работы с режимами автоматических и управляемых блокировок в 1С Предприятие 8. Теория и применение в типовых конфигурациях: БП, УТ, ЕРП

10.11.2018    35146    ids79    40    

Возможности типовых шаблонов ограничения доступа на уровне записей (RLS)

Практика программирования БСП (Библиотека стандартных подсистем) Роли и права v8 v8::Права Бесплатно (free)

Краткий обзор применения типовых шаблонов ограничения доступа на уровне записей в конфигурациях, созданных на базе БСП: #ПоЗначениям, #ПоНаборамЗначений, #ПоЗначениямРасширенный, #ПоЗначениямИНаборамРасширенный

03.02.2019    40436    ids79    9    

Тестер: частые вопросы Промо

Практика программирования v8 Бесплатно (free)

Ошибкам бой - тесты норма жизни!

25.07.2018    29360    grumagargler    28    

EnterpriseData – часть 2. Процесс выгрузки данных

Практика программирования Обмен через XML v8 v8::УФ Россия Бесплатно (free)

Основные этапы выгрузки данных через ED, обработчики событий выгрузки, правила обработки данных, правила конвертации объектов, конвертация свойств первого и второго этапов, процедуры БСП, используемые при выгрузке данных, структура «КомпонентыОбмена».

26.12.2018    27134    ids79    31    

Новый подход к обмену данными EnterpriseData

Практика программирования Обмен через XML v8 v8::УФ Россия Бесплатно (free)

Хочу предложить Вашему вниманию цикл статей, посвященных обмену данными через универсальный формат (EnterpriseData или ED).

14.12.2018    42007    ids79    72    

EnterpriseData - пример доработки правил конвертации без использования КД 3.0 в расширении конфигурации

Практика программирования Обмен через XML v8 v8::УФ БП3.0 УТ11 Россия Бесплатно (free)

В статье подробно описан реальный пример доработки обмена данными через EnterpriseData (универсальный формат обмена) между конфигурациями УТ 11.4 и Бухгалтерия 3.0

16.11.2018    37582    ids79    42    

Ускоряем 1С: модули с повторным использованием возвращаемых значений Промо

Практика программирования v8 Бесплатно (free)

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

04.09.2017    53028    m-rv    61    

Программное заполнение пользовательских параметров и отборов СКД

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Публикация представляет из себя краткие примеры того, как можно заполнять параметры СКД программно так, чтобы все параметры и отборы были доступны в быстрых настройках и в обычных (типовых) настройках параметров и отборов СКД.

13.11.2018    48736    Unk92    25