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 11:54]
celutp
developer:linq [2011/09/14 12:17] (current)
celutp
Line 11: Line 11:
 ===== Предварительная настройка =====      ===== Предварительная настройка =====     
   * В [[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 41: Line 41:
 Сборка контентов QP7 в классы //​LINQ-to-SQL//​ может осуществляться в двух режимах:​ Сборка контентов QP7 в классы //​LINQ-to-SQL//​ может осуществляться в двух режимах:​
  
-  - С использованием БД. При этом будут использованы специальные настройки LINQ-to-SQL,​ которые задаются в свойствах контентов и полей. +  - [[developer:​linq:​db_mapping|С использованием БД]]. При этом будут использованы специальные настройки LINQ-to-SQL,​ которые задаются в свойствах ​сайта, ​контентов и полей. 
-  - С использованием ​[[developer:​linq:​mapping| ​пользовательского файла отображения]]. При этом файл может быть как составлен разработчиком вручную,​ так и сгенерирован бэкендом по умолчанию.+  - [[developer:​linq:​mapping|С использованием пользовательского файла отображения]]. При этом файл может быть как составлен разработчиком вручную,​ так и сгенерирован бэкендом по умолчанию.
  
 Переключение режимов осуществляется опцией **Использовать прямое отображение из базы данных** (**Use direct mapping from database**) на [[:​site_configuration#​Настройки_сборки_в_LINQ|уровне сайта]]. Cама сборка запускается кнопкой **Собрать Контенты** (**Assemble Contents**) на странице **Контенты** (**Contents**). При этом в папке //​App_Code//​ происходит полная перегенерация всех LINQ-классов текущего сайта. Следует иметь в виду, что данный процесс с большой долей вероятности приведет к перегрузке домена приложения,​ поэтому его стоит с осторожностью применять на продукционных сайтах. Переключение режимов осуществляется опцией **Использовать прямое отображение из базы данных** (**Use direct mapping from database**) на [[:​site_configuration#​Настройки_сборки_в_LINQ|уровне сайта]]. Cама сборка запускается кнопкой **Собрать Контенты** (**Assemble Contents**) на странице **Контенты** (**Contents**). При этом в папке //​App_Code//​ происходит полная перегенерация всех LINQ-классов текущего сайта. Следует иметь в виду, что данный процесс с большой долей вероятности приведет к перегрузке домена приложения,​ поэтому его стоит с осторожностью применять на продукционных сайтах.
Line 48: Line 48:
 Кроме этого, на [[:​site_configuration#​Настройки_сборки_в_LINQ|уровне сайта]] существует опция **Импортировать файл отображения в базу данных**(**Import mapping file to database**),​ которая позволяет импортировать существующий [[developer:​linq:​mapping|пользовательский файл отображения]] в базу данных для последующей настройки через бэкенд QP7 и генерации файла отображения в автоматическом режиме. При успешном выполнении импорта данная опция автоматически сбрасывается,​ а опция **Использовать прямое отображение из базы данных** (**Use direct mapping from database**) автоматически устанавливается. ​ Кроме этого, на [[:​site_configuration#​Настройки_сборки_в_LINQ|уровне сайта]] существует опция **Импортировать файл отображения в базу данных**(**Import mapping file to database**),​ которая позволяет импортировать существующий [[developer:​linq:​mapping|пользовательский файл отображения]] в базу данных для последующей настройки через бэкенд QP7 и генерации файла отображения в автоматическом режиме. При успешном выполнении импорта данная опция автоматически сбрасывается,​ а опция **Использовать прямое отображение из базы данных** (**Use direct mapping from database**) автоматически устанавливается. ​
  
-Опция **Импортировать файл отображения в базу данных**(**Import mapping file to database**) также может быть полезна для первичного заполнения настроек LINQ-to-SQL для существующего сайта с большим количеством контентов. Для этого сначала генерируется ​[[developer:​linq:​mapping| ​пользовательский файл отображения]] по умолчанию (при отключенной опции **Использовать прямое отображение из базы данных** (**Use direct mapping from database**),​ а затем проводится его импорт.+Опция **Импортировать файл отображения в базу данных**(**Import mapping file to database**) также может быть полезна для первичного заполнения настроек LINQ-to-SQL для существующего сайта с большим количеством контентов. Для этого сначала генерируется пользовательский файл отображения по умолчанию (при отключенной опции **Использовать прямое отображение из базы данных** (**Use direct mapping from database**),​ а затем проводится его импорт.
  
 +Генерация LINQ-to-SQL классов и вспомогательных файлов осуществляется в папки //​App_Data//​ и //​App_Code//​ сайта. Расположение этих папок вычисляется из расположения папки //bin//, которая настраивается в [[:​site_configuration#​папка_для_net-сборок|свойствах сайта]]. При этом предполагается,​ что папки //​App_Data//​ и //​App_Code//​ находятся на том же уровне в дереве папок, что и //​bin//​. ​
  
  
 +===== Использование сгенерированных LINQ-to-SQL классов =====
  
-===== Особенности механизма генерации LINQ-классов ​=====+  - [[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 ​классов]]
  
-====  ​Статический DataContext ​====  +===== Пример добавления статьи =====
-Доступен как **LinqHelper.Context**. Рекомендуется к использованию вместо создания каждый раз нового контекста через ''​using (QPDataContext ctx = new QPDataContext())'',​ кроме тех случав,​ когда необходимо работать с несколькими контекстами сразу. +
- +
- +
- +
-====  ​Поддержка фильтрации M2M-полей на уровне SQL ====  +
- +
-Для этого генерируются отдельные узловые классы для каждой связи. ​ На уровне БД эти классы отображаются на специальные представления (//​LINK_NNN//​),​ которые ссылаются на единую физическую таблицу //​ITEM_TO_ITEM//​. Все используемые узловые сущности генерируются автоматически,​ если же необходимо заменить их названия,​ это можно сделать в настройках поля Many-To-Many или через тег ''​link''​ [[developer:​linq:​mapping|файла отображения]],​ задав в качестве идентификатора атрибут ID, и желаемые имена – в атрибутах //​mapped_name//​ и //​mapped_plural_name//​.  +
- +
-При написании 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 93: 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.1304585655.txt.gz · Last modified: 2011/05/05 11:54 by celutp