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

Опубликовал Serginio в раздел Программирование - Практика программирования

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

Здесь лежит практика использования http://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спрinthis.Set<TEntity>()

                         whereспр.ID == ID

                         selectспр;

            return query.SingleOrDefault<TEntity>();

 

        }

 

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

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

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

    {

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

        [MaxLength(8)]

        [Timestamp]

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

       

        [Column("_Marked")]

        [Required]

        [MaxLength(1)]

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

 

        [Column("_PREDEFINEDID")]

        [Required]

        [MaxLength(16)]

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

 

        [NotMapped]

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

        {

            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  publicstring 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  publicbyte[] Тип { get; set; }

 

[Column("_Fld37_L")]

[Required]

[MaxLength(1)]

publicbyte[] Булево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]

publicboolБулево {

   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значение(НТС.Ссылка);

 

                    returnnull;

        }

        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)

                       returnnull;

 

                   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)]

        publicbyte[] KeyField { get; set; }

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

 

 

    }

 

 

[Table("_Reference10_VT31")]

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

{

   [Key]

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

   [MaxLength(16)]

  override  publicbyte[] Ссылка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

    {

 

        publicstaticbyte[] В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данные)

        {

 

            returnBitConverter.GetBytes(данные);

        }

 

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

        {

 

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

        }

    }

См. также

Лучшие комментарии

1. WKBAPKA 25.09.2015 09:02
тысяча чертей! что это?
# Ответить

Комментарии

1. WKBAPKA 25.09.2015 09:02
тысяча чертей! что это?
# Ответить
3. RomanRomans 28.09.2015 21:31
умопомрачительно
Ответили: (4)
# Ответить
4. Serginio 29.09.2015 14:18
(3) Да нет все очень прозрачно и понятно. Просто нужно уметь готовить
Ответили: (5)
# Ответить
5. baracuda 06.10.2015 15:30
(4) Serginio, Для описания формирования классов добавляется в проект как ссылка на публикуемый интерфейс ODATA в SERVICE REFERENCE?
# Ответить
6. Serginio 06.10.2015 16:55
Нет. Для этого в части I есть обработка которая формирует модули
http://infostart.ru/public/393228/
# Ответить
7. утюгчеловек 08.05.2016 22:38
Очень круто.

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

И кстати ни в одной из статей серии нет выводов.
# Ответить
8. Serginio 09.05.2016 08:51
Прежде всего это нужно для интеграции с другими программами. В том числе и Asp.Net. Если в 8.x есть вэб,HTTP сервисы,ODATA. То в 7 ке грустно. COM медленный. И главное это скорость выполнения и программирования
# Ответить
Внимание! За постинг в данном форуме $m не начисляются.
Внимание! Для написания сообщения необходимо авторизоваться
Текст сообщения*
Прикрепить файл