User Tools

Site Tools


developer:linq

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
developer:linq [2011/05/05 10:10]
celutp
developer:linq [2011/09/14 12:17] (current)
celutp
Line 8: Line 8:
   * Добавляется возможность редактирования статей с помощью LINQ-классов. Что вместе с предыдущим пунктом дает возможность использования,​ например,​ редактируемого Grid для контентов QP7.   * Добавляется возможность редактирования статей с помощью LINQ-классов. Что вместе с предыдущим пунктом дает возможность использования,​ например,​ редактируемого Grid для контентов QP7.
   * Связанные таблицы становятся доступными как свойства (включая связи многие-ко-многим).   * Связанные таблицы становятся доступными как свойства (включая связи многие-ко-многим).
- 
-===== Aрхитектура решения ===== 
- 
-==== Настройка сборки классов LINQ-to-SQL ​ ==== 
-Сборка контентов QP7 в классы //​LINQ-to-SQL//​ может осуществляться в двух режимах:​ 
- 
-  - С использованием БД. При этом будут использованы специальные настройки LINQ-to-SQL,​ которые задаются в свойствах контентов и полей. 
-  - С использованием [[developer:​linq:​mapping| пользовательского файла отображения]]. При этом файл может быть как составлен разработчиком вручную,​ так и сгенерирован бэкендом по умолчанию. 
- 
-Переключение режимов осуществляется опцией **Использовать прямое отображение из базы данных** (**Use direct mapping from database**) на [[:​site_configuration#​Настройки_сборки_в_LINQ|уровне сайта]]. Cама сборка запускается кнопкой **Собрать Контенты** (**Assemble Contents**) на странице **Контенты** (**Contents**). 
- 
- 
- 
-==== Генерация классов ==== 
-Процесс сборки кода запускается кнопкой **Собрать Контенты** (**Assemble Contents**) на вкладке на странице **Контенты** (**Contents**) ​ в бэкенде QP7. При этом в папке //​App_Code//​ происходит полная перегенерация всех LINQ-классов текущего сайта в соответствии с [[developer:​linq:​mapping|файлом отображения]]. Следует иметь в виду, что данный процесс с большой долей вероятности приведет к перегрузке домена приложения,​ поэтому его стоит с осторожностью применять на продукционных сайтах. Более подробно алгоритм генерации описан [[developer:​linq:​assembling|здесь]]. 
  
 ===== Предварительная настройка =====      ===== Предварительная настройка =====     
   * В [[admin:​config|конфигурационный файл Backend]] нужно добавить параметр **SqlMetalPath**,​ определяющий путь к стандартной утилите генерации SQL-классов. Данная утилита устанавливатся вместе с Visual Studio 2008. Путь к ней может выглядеть так: ''​C:​\Program Files\Microsoft SDKs\Windows\v6.0A\bin\sqlmetal.exe''​. Если на целевом компьютере не установлена Visual Studio, утилиту можно просто [[http://​downloads.quantumart.ru/​sqlmetal.zip|скачать]].   * В [[admin:​config|конфигурационный файл Backend]] нужно добавить параметр **SqlMetalPath**,​ определяющий путь к стандартной утилите генерации SQL-классов. Данная утилита устанавливатся вместе с Visual Studio 2008. Путь к ней может выглядеть так: ''​C:​\Program Files\Microsoft SDKs\Windows\v6.0A\bin\sqlmetal.exe''​. Если на целевом компьютере не установлена Visual Studio, утилиту можно просто [[http://​downloads.quantumart.ru/​sqlmetal.zip|скачать]].
-  * Необходимо дать право доступа //Modify// пользователю NETWORK SERVICE на папку //​App_Code//​ для возможности генерации файлов классов и папку //​App_Data//​ для генерации промежуточных файлов отображений.+  * Необходимо дать право доступа //Modify// пользователю, под которым запущен Application Pool (обычно это ​NETWORK SERVICE), на папку //​App_Code//​ для возможности генерации файлов классов и папку //​App_Data//​ для генерации промежуточных файлов отображений.
   * В процессе работы утилита **SQLMetal** может выдавать ошибки,​ которые можно посмотреть в файле //​sqlmetal.log//​ в папке //​App_Data//​. Ошибки обычно связаны с конфликтами имен.   * В процессе работы утилита **SQLMetal** может выдавать ошибки,​ которые можно посмотреть в файле //​sqlmetal.log//​ в папке //​App_Data//​. Ошибки обычно связаны с конфликтами имен.
   * Если на сайте не использовался LINQ-to-SQL,​ то необходимо добавить в //​web.config//​ ссылки на соответствующие сборки:​   * Если на сайте не использовался LINQ-to-SQL,​ то необходимо добавить в //​web.config//​ ссылки на соответствующие сборки:​
Line 53: Line 38:
 </​code>​ </​code>​
  
 +===== Настройка сборки контентов в классы LINQ-to-SQL ​ =====
 +Сборка контентов QP7 в классы //​LINQ-to-SQL//​ может осуществляться в двух режимах:​
  
 +  - [[developer:​linq:​db_mapping|С использованием БД]]. При этом будут использованы специальные настройки LINQ-to-SQL,​ которые задаются в свойствах сайта, контентов и полей.
 +  - [[developer:​linq:​mapping|С использованием пользовательского файла отображения]]. При этом файл может быть как составлен разработчиком вручную,​ так и сгенерирован бэкендом по умолчанию.
  
 +Переключение режимов осуществляется опцией **Использовать прямое отображение из базы данных** (**Use direct mapping from database**) на [[:​site_configuration#​Настройки_сборки_в_LINQ|уровне сайта]]. Cама сборка запускается кнопкой **Собрать Контенты** (**Assemble Contents**) на странице **Контенты** (**Contents**). При этом в папке //​App_Code//​ происходит полная перегенерация всех LINQ-классов текущего сайта. Следует иметь в виду, что данный процесс с большой долей вероятности приведет к перегрузке домена приложения,​ поэтому его стоит с осторожностью применять на продукционных сайтах.
  
-===== Особенности механизма генерации ​LINQ-классов ​=====+Кроме этого, на [[:​site_configuration#​Настройки_сборки_в_LINQ|уровне сайта]] существует опция **Импортировать файл отображения в базу данных**(**Import mapping file to database**),​ которая позволяет импортировать существующий [[developer:​linq:​mapping|пользовательский файл отображения]] в базу данных для последующей настройки через бэкенд QP7 и генерации ​файла отображения в автоматическом режиме. При успешном выполнении импорта данная опция автоматически сбрасывается,​ а опция **Использовать прямое отображение из базы данных** (**Use direct mapping from database**) автоматически устанавливается. ​
  
-====  Статический DataContext ====  +Опция **Импортировать файл отображения в базу данных**(**Import mapping file to database**) также может быть ​полезна для первичного заполнения ​настроек LINQ-to-SQL ​для существующего сайта с большим количеством контентов. Для этого сначала генерируется пользовательский файл отображения по умолчанию (при отключенной опции **Использовать ​прямое отображение из базы данных** (**Use direct mapping from database**),​ а затем ​проводится его импорт.
-Доступен как **LinqHelper.Context**. Рекомендуется к использованию вместо создания ​каждый раз нового контекста через ​''​using (QPDataContext ctx = new QPDataContext())'',​ кроме тех случав, когда необходимо работать ​с несколькими контекстами сразу.+
  
 +Генерация LINQ-to-SQL классов и вспомогательных файлов осуществляется в папки //​App_Data//​ и //​App_Code//​ сайта. Расположение этих папок вычисляется из расположения папки //bin//, которая настраивается в [[:​site_configuration#​папка_для_net-сборок|свойствах сайта]]. При этом предполагается,​ что папки //​App_Data//​ и //​App_Code//​ находятся на том же уровне в дереве папок, что и //​bin//​. ​
  
  
-====  Поддержка фильтрации M2M-полей на уровне SQL ==== +===== Использование сгенерированных LINQ-to-SQL классов =====
  
-Для этого генерируются отдельные узловые классы для каждой связи. ​ На уровне БД эти классы отображаются на специальные представления ​(//​LINK_NNN//​),​ которые ссылаются на единую физическую таблицу //​ITEM_TO_ITEM//​. Все используемые узловые сущности генерируются автоматически,​ если же необходимо заменить их названия, это можно сделать в настройках ​поля Many-To-Many ​или через тег ''​link'' ​[[developer:​linq:​mapping|файла отображения]]задав в качестве идентификатора атрибут ID, и желаемые имена – в атрибутах //​mapped_name//​ и //​mapped_plural_name//​. ​+  - [[developer:​linq:​context|Использование контекстного ​класса]] 
 +  - [[developer:​linq:​M2M|Работа с M2M-полями]] 
 +  - [[developer:​linq:​container|Поддержка поведения ​Publishing Container]] 
 +  - [[developer:​linq:​service_field|Поддержка служебных ​полей контента]] 
 +  - [[developer:​linq:​image|Дополнительные свойства ​для ​полейзображений]] 
 +  - [[developer:​linq:​caching|Кэширование]] 
 +  - [[developer:​linq:​components|Создание ​компонентов]] 
 +  - [[developer:​linq:​errors|Основные ошибки использования LINQ-to-SQL классов]]
  
-При написании LINQ-запроса с фильтрацией по M2M-полю на уровне SQL алгоритм следующий:​  +===== Пример добавления статьи =====
-    * начинаем с узловой сущности +
-    * фильтруем по одной связанной сущности  +
-    * делаем проекцию по второй связанной сущности +
-<code c#>​IQueryable<​Article>​ art ctx.ArticlesCategories.Where(n ​=> n.Category.Title ​== "​main"​).Select(m ​=> m.Article);</​code>​ +
- +
-====  ​Поддержка механизмом отслеживания изменений полей M2M. ====   +
-Для изменения полей M2M достаточно только вызывать методы //Add// и //Remove// соответствующей коллекции. Никакие другие поля для срабатывания механизма отслеживания изменений изменять не надо.  +
- +
-====  Автоматическая замена плейсхолдеров ====  +
-Поддержка стандартного поведения Publishing Container ([[edit:​url_auto_replace|подробнее]]) Замена плейсхолдеров ''<​%=site_url%>''​ и ''<​%=upload_url%>''​ производится для полей типа //String//, //​VisualEdit//​ и //​Textbox//​. Замена работает в обе стороны,​ как при загрузке,​ так и при сохранении. Для включения этого механизма необходимо у тега ''​schema''​ в [[developer:​linq:​mapping|файле отображения]] выставить атрибут ''​replaceUrls="​true"''​. ​ Кроме того установкой атрибута ''​useLongUrls="​true"''​ можно модифицировать поведение механизма,​ замены так, что плейсхолдеры будут заменяться на абсолютные URL, а не на относительные. +
- +
-==== Фильтрация по умолчанию ==== +
-Поддержка стандартного поведения Publishing Container. Необходимо для того, чтобы работало расписание публицкации,​ workflow, архив. В предыдущих версиях реализовалось через вызов метода расширения  +
-**ForFrontEnd()**. В текущей версии метод оставлен для обратной совместимости,​ но в случае включенной фильтрации по умолчанию никаких действий не выполняет. Опция **Использовать фильтрацию по умолчанию** (**Use default filtration**) настраивается [[:​content|на уровне контента]]. При включенной опции LINQ-класс отображается не на таблицу CONTENT_NNN,​ а на представление CONTENT_NNN_LIVE (для stage-режима используется аналогичное представление CONTENT_NNN_STAGE вместо CONTENT_NNN_UNITED) +
-  +
- +
-==== Улучшенная логика служебных полей ==== +
-    * Альтернативные свойства для служебных полей в соответствии с Pascal-нотацией:​ //​Created//,​ //​Modified//,​ //​LastModifiedBy//,​ //Visible// (bool), //Archive// (bool), //​StatusType//​ (ссылка на соответствующий тип). Старые названия поддерживаются для обратной совместимости. +
-    * Автообновление полей //Created// и //​Modified//​ при соответствующих событиях (//​SubmitChanges//​) +
-    * Автосоздание служебных полей (//​Visible//,​ //​Archive//,​ //​StatusType//​) при создании нового экземпляра класса и возможность их изменения. +
- +
-===== Пример использования для ​добавления статьи =====+
 <code c#> <code c#>
  NewsArticle art = new NewsArticle();​  NewsArticle art = new NewsArticle();​
Line 97: Line 72:
  LinqHelper.Context.SubmitChanges();​  LinqHelper.Context.SubmitChanges();​
 </​code>​ </​code>​
- 
-===== LINQ-классы и кэширование ===== 
- 
-В //​quantumart.dll//​ добавлен обобщенный (generic) метод кэширования //​GetCachedEntity//:​ 
- 
-<code c#> 
-public T GetCachedEntity<​T>​(string key, Func<​T>​ fillAction) 
-public T GetCachedEntity<​T>​(string key, Func<​string,​ T> fillAction) 
-public T GetCachedEntity<​T>​(string key, double cacheInterval,​ Func<​T>​ fillAction) 
-public T GetCachedEntity<​T>​(string key, double cacheInterval,​ Func<​string,​ T> fillAction) 
-</​code>​ 
-Основное назначение:​ кэширование произвольных пользовательских коллекций,​ в том числе полученных с помощью LINQ. Обычно это: //​Dictionary<​K,​ V>//, //​List<​T>//​. 
- 
-Пример использования:​ 
- 
-<code c#> 
-DBConnector cnn = new DBConnector();​ 
-List<​Banner>​ banners = cnn.CacheManager.GetCachedEntity<​List<​Banner>>​(pageAddress,​ 10, GetPageBanners);​ 
-</​code>​ 
- 
-Где //​GetPageBanners//​ – метод, возвращающий //​List<​Banner>//,​ который будет вызван только при заполнении кэша. Метод может быть определен как без параметров,​ так и с единственным строковым параметром. Во втором случае в метод будет передано значение ключа (параметр //key//). 
- 
-Метод может использоваться для кэширования любых ссылочных типов. Для того, чтобы кэшировать значимый тип (value type), необоходимо выполнить принудительный //boxing// (число можно для этого, например,​ преобразовать в строку). Данный метод также позволяет кэшировать //​null//​-значения,​ используя для них специальную обертку. 
- 
-===== Основные ошибки использования LINQ-классов ===== 
- 
-  * Многократное выполнение одних и тех же запросов без необходимости. 
-  * Отсутствие понимания,​ что выполняется на веб-сервере,​ а что -- на сервере баз данных  ​ 
-  * Получение от SQL-сервера лишней информации (аналог в SQL -- //select *//), когда можно обойтись ограниченным набором полей с помощью //select new//. 
-  * В конце цепочки операций LINQ в большинстве случаев желательно явно овеществлять результат (например,​ с помощью //​ToList()//​). Результат должен быть не //​IQueryable<​T>//,​ а //​IEnumerable<​T>//​ или T, иначе последующий //foreach// может привести к новому SQL-запросу на каждой итерации. 
  
  
developer/linq.1304579415.txt.gz · Last modified: 2011/05/05 10:10 by celutp