tag:blogger.com,1999:blog-73091848166343812482024-03-13T22:57:02.963+03:00О разработке ПО и эффективностиМетоды и инструменты эффективной разработки приложений.Олег Аксёновhttp://www.blogger.com/profile/04146413181790640824noreply@blogger.comBlogger34125tag:blogger.com,1999:blog-7309184816634381248.post-36757932016935764562019-02-08T23:38:00.001+03:002019-02-08T23:40:07.355+03:00Про судьбу этого блога и YarFullStack<p>Внимательные читатели наверняка заметили, что я давно сюда не писал :)</p>
<p>Дело в том, что пару лет назад я начал писать немного в другом формате в другой блог - <a href="https://yarfullstack.com/post/about/" target="_blank">YarFullStack</a>.
Основное отличие в том, что там более короткие и менее "образовательные" сообщения на более широкие темы. А ещё - я полностью управляю его дизайном и наличием (то есть, отсутствием) рекламы, аналитики и т.п.</p>
<p>Это "переформатирование" мне понравилось. А ещё 2016 год стал для меня временем многих перемен. Что, конечно, не извиняет меня за отсутствие всех этих пояснений здесь два года назад. Исправляюсь.</p>
<p>Буду ли я писать сюда что-то новое? В ближайшее время - вряд ли. Скорее всего, буду делать краткие дайджесты из нескольких статей с <a href="https://yarfullstack.com/" target="_blank">YarFullStack</a>.
Так что, если хотите - читайте их здесь. А можете подписаться на <a href="https://twitter.com/YarFS" target="_blank" rel="nofollow noopener noreferrer">Twitter</a> или <a href="https://t.me/yarfullstack" target="_blank" rel="nofollow noopener noreferrer">Telegram</a> нового проекта, чтобы получать их оперативнее.
</p>
<p>P.S. Единственное, что может вам показаться непривычным на новом сайте - отсутствие комментариев. Раньше там был disqus, но он тормозной и бесящий. Поэтому пока единственный вариант комментариев - в твиттере. Или здесь :)</p>Олег Аксёновhttp://www.blogger.com/profile/04146413181790640824noreply@blogger.com0tag:blogger.com,1999:blog-7309184816634381248.post-46734709627084160432014-12-03T00:07:00.001+03:002014-12-03T00:10:56.093+03:00MSSQL – простые индикаторы нехватки индексов<p>Как обычно в нашей профессии, есть несколько способов решить задачу :)</p> <p>Расскажу о трёх наиболее простых подходах (и одном бонусном), не углубляясь в детали. Если интересны как раз глубокие детали, рекомендую почитать документацию (начать стоит с <a href="http://technet.microsoft.com/en-us/library/ms190804(v=sql.105).aspx" rel="nofollow" target="_blank">Designing Indexes</a>, а прочитав о проектировании продолжить <a href="http://technet.microsoft.com/en-us/library/bb510669(v=sql.105).aspx" rel="nofollow" target="_blank">Performance (Database Engine)</a>).</p> <p>Кстати, если тема плана выполнения для вас нова – неплохим стартом будет мой давний пост «<a href="http://www.olegaxenow.com/2011/04/sql-execution-plan.html" target="_blank">SQL – execution plan</a>».</p> <p><strong>DISCLAIMER</strong>: в этой статье я даю простые советы, которые чаще всего работают, однако в MSSQL практически невозможно дать рекомендации на все случаи жизни – данные бывают разные, запросы бывают разные…</p> <h2>1. Мысленный эксперимент</h2> <p>Достаточно полезный способ, особенно на этапе проектирования. Хорошим подспорьем для тех, кому индексы в новинку, будет вышеупомянутый раздел про дизайн индексов.</p> <p>Что касается простейших советов, они следующие:</p> <ol> <li>Если данных не мизерное количество – вам нужны индексы. <li>Если есть внешние ключи – настоящие или по смыслу (некоторые их принципиально не любят делать) – они хорошие кандидаты для индексирования. <li>Чаще всего стоит сделать кластерный индекс и сделать его не слишком большим (потому что другие индексы будут ссылаться на строки по кластерному индексу). Кстати, кластерный индекс отлично подходит для выборки по диапазону (например, по диапазону дат). <li>Помните, что индексы тоже хранятся на диске. Простейший вывод – большое количество индексов снизит скорость вставки (иногда и обновления) данных. Обычно до создания 5-7 индексов проблем не возникает. <li>Статистика очень важна для правильного использования индексов. Хорошая новость – чаще всего MSSQL сам достаточно неплохо за ней следит, плохая новость – это не всегда срабатывает. <li>Для наиболее критичных запросов, возвращающих небольшое количество столбцов, имеет смысл использовать покрытие индексом (это уже чуть более продвинутая техника, но ничего сложного в ней нет).</li> <p>Поскольку я обещал не углубляться в детали – идём дальше.</p> </li></li></li></li></li></ol><a href="http://www.olegaxenow.com/2014/12/mssql-prostye-indikatory-nehvatki.html#more">Дальше »</a>Олег Аксёновhttp://www.blogger.com/profile/04146413181790640824noreply@blogger.com1tag:blogger.com,1999:blog-7309184816634381248.post-64433562310369065582014-01-21T23:06:00.001+04:002014-01-21T23:08:54.555+04:00Практическое применение Integration Services<p>Изложение не претендует на полноту, сейчас я хочу показать лишь некоторые возможности SSIS, чтобы вы могли приблизительность оценить целесообразность его использования. А уже в случае такого выбора - изучать предмет более досконально.</p> <h2>1. Базы данных для примера</h2> <p>В примерах используется база данных <a href="http://msftdbprodsamples.codeplex.com/releases/view/55330" rel="nofollow">AdventureWorks</a> в качестве источника и простая база, которую легко можно сделать самостоятельно в качестве приёмника данных. Важно понимать, что примеры приводятся искусственные, в реальной жизни всё может быть несколько сложнее.</p> <p>Итак, перед началом работы нам понадобится экземпляр MS SQL Server 2012 с установленной на нём БД <a href="http://msftdbprodsamples.codeplex.com/releases/view/55330" rel="nofollow">AdventureWorks</a> и созданной тестовой БД, назовём её TestSSIS. Для обучения проще держать MS SQL на том же компьютере, на котором будем работать с проектом Integration Services.</p> <a href="http://www.olegaxenow.com/2014/01/prakticheskoe-primenenie-integration.html#more">Дальше »</a>Олег Аксёновhttp://www.blogger.com/profile/04146413181790640824noreply@blogger.com2tag:blogger.com,1999:blog-7309184816634381248.post-80917806599516741522014-01-21T23:02:00.001+04:002014-01-21T23:03:05.944+04:00Распространённые технологии импорта данных<p>Под распространёнными технологиями подразумеваются те, которые часто используются для импорта данных. Разумеется, для некоторых задач чаще могут использоваться технологии импорта, которые не вошли в список ниже.</p> <h2>1. BULK INSERT/bcp</h2> <p><a href="http://technet.microsoft.com/en-us/library/ms162802.aspx" rel="nofollow">bcp</a> - это утилита командной строки для импорта/экспорта данных, входящая в состав Microsoft SQL Server 2012 tools (для более ранних версий она тоже присутствует). <a href="http://technet.microsoft.com/en-us/library/ms188365.aspx" rel="nofollow">BULK INSERT</a> - команда T-SQL, позволяющая импортировать данные тем же способом что и bcp, но без использования командной строки.</p> <p>Основное назначение bcp - быстрое копирование данных между аналогичными по структуре таблицами. В принципе, с помощью файла формата (указанного в качестве опции) можно копировать данные между таблицами с разной структурой. Нередко используется копирование с помощью bcp в промежуточные таблицы, из которых средствами T-SQL данные преобразуются в итоговые таблицы.</p> <p>В простом случае, сначала данные экспортируют из таблицы в файл, а потом из файла импортируют в другую таблицу (в т.ч. в другой БД или на другом сервере). В принципе, файл можно подготовить и другими средствами. Например, можно использовать csv-файлы, но с <a href="http://technet.microsoft.com/en-us/library/ms188609.aspx" rel="nofollow">ограничениями</a>.</p> <a href="http://www.olegaxenow.com/2014/01/rasprostranjonnye-tehnologii-importa.html#more">Дальше »</a>Олег Аксёновhttp://www.blogger.com/profile/04146413181790640824noreply@blogger.com0tag:blogger.com,1999:blog-7309184816634381248.post-58154031185132038172014-01-16T21:27:00.001+04:002014-01-16T21:28:08.037+04:00Импорт данных с точки зрения бизнеса<p>Эта статья открывает небольшой цикл статей об импорте данных. Перед тем, как говорить об импорте данных, имеет смысл понять, какие бизнес-задачи решает импорт. Обычно функциональность импорта решает одну из трех задач, обсуждаемых ниже.</p> <h2>1. Первоначальный/разовый импорт</h2> <p>Без первоначального импорта данных редко обходится внедрение любого нового решения, которое приходит на смену старому.</p> <p>Часто бывает, что старое решение использует разнородные (или как модно говорить - гетерогенные) источники данных. Это могут быть несколько СУБД, файлы Excel или даже просто текстовые файлы. Но даже в случае, когда источник данных - единственная БД того же производителя, задача может быть не очень тривиальной, учитывая различия в структуре данных. </p> <p>Обычно для первоначального импорта в MS SQL Server используются Integration Services, BULK INSERT (или утилита командной строки bcp) или написанный специально для этой задачи программный код. Подробнее об этих технологиях будет рассказано далее.</p> <h2>2. Интеграция с помощью БД</h2> <p>Как вы наверняка знаете, часто требуется интеграция между несколькими программными продуктами (часто даже входящими в одно решение от единственного производителя).</p> <a href="http://www.olegaxenow.com/2014/01/import-dannyh-s-tochki-zrenija-biznesa.html#more">Дальше »</a>Олег Аксёновhttp://www.blogger.com/profile/04146413181790640824noreply@blogger.com0tag:blogger.com,1999:blog-7309184816634381248.post-55660472034403306832013-11-16T21:40:00.001+04:002013-11-16T21:46:20.716+04:00SQL-скрипты для поиска данных<p>Иногда мы точно знаем что и где искать, иногда только приблизительно знаем что и лишь догадываемся где. Хочу поделиться несколькими скриптами под MS SQL Server для последнего случая.</p> <h2>Поиск объектов во всех базах данных сервера</h2> <p>У вас бывало, что нужно найти таблицу чтобы посмотреть данные или структуру, а вы не помните точно в какой БД она находится? У меня, периодически, такое случается. Пример - найти таблицы из проекта пятилетней давности, чтобы посмотреть как тогда решал текущую задачу.</p> <p>К счастью, есть процедура <em>sp_MSforeachdb</em>, которая позволяет написать такой скрипт довольно компактно:</p><pre class="csharpcode"><span class="kwrd">DECLARE</span> @name <span class="kwrd">AS</span> SYSNAME,<br /> @strSQL <span class="kwrd">AS</span> <span class="kwrd">VARCHAR</span>(<span class="kwrd">MAX</span>)<br /><span class="kwrd">SET</span> @name = <span class="str">'Hierarchy'</span><br /><br /><span class="kwrd">SET</span> @strSQL = <span class="str">'<br />IF EXISTS(SELECT * FROM ?..sysobjects WHERE name LIKE '</span><span class="str">'%'</span>+@name+<span class="str">'%'</span><span class="str">')<br />BEGIN<br /> SELECT '</span><span class="str">'?'</span><span class="str">' db, name FROM ?..sysobjects WHERE name LIKE '</span><span class="str">'%'</span>+@name+<span class="str">'%'</span><span class="str">'<br />END<br />'</span><br /><span class="kwrd">CREATE</span> <span class="kwrd">TABLE</span> #<span class="kwrd">result</span>(<br /> db SYSNAME,<br /> name SYSNAME,<br /> <span class="kwrd">PRIMARY</span> <span class="kwrd">KEY</span>(db,name))<br /><br />INSERT #<span class="kwrd">result</span> <span class="kwrd">EXEC</span> sp_MSforeachdb @strSQL<br /><span class="kwrd">SELECT</span> * <span class="kwrd">FROM</span> #<span class="kwrd">result</span><br /><br /><span class="kwrd">DROP</span> <span class="kwrd">TABLE</span> #result</pre><p>Здесь всё достаточно просто:</p><ol><li>Задаём часть названия, по которому будем искать (в данном случае - Hierarchy).</li><li>Собираем динамический SQL, который ищет по sysobjects (для некоторых старых версий MS SQL можно вместо VARCHAR(MAX) использовать VARCHAR(2000), например).<br>При этом символ "?" заменится на название БД. </li><li>С помощью конструкции INSERT ... EXEC сохраняем все результаты во временную таблицу, чтобы отобразить, в итоге, единый результат.</li></ol><h2>Поиск подстроки в текстах хранимых процедур</h2><p>Как вы знаете, тексты хранимых процедур, триггеров и представлений можно найти в таблице <em>syscomments</em>.</p><p>Чтобы наш предыдущий запрос позволил нам найти упоминание в syscomments некоторой подстроки, его можно переписать следующим образом:</p><pre class="csharpcode"><span class="kwrd">SET</span> @strSQL = <span class="str">'<br />SELECT DISTINCT '</span><span class="str">'?'</span><span class="str">' as db, o.name FROM [?].dbo.syscomments s<br />JOIN [?].dbo.sysobjects o ON o.id = s.id WHERE s.[text] LIKE '</span><span class="str">'%'</span>+@name+<span class="str">'%'</span><span class="str">''</span></pre><p>Обратите внимание на DISTINCT - может пригодиться, потому что иногда для одного объекта бывает несколько записей в syscomments.</p><h2>Поиск подстроки во всех строковых полях всех таблиц</h2><p>Такой скрипт здорово помогает спать спокойно после "чистки" базы перед отправкой клиенту. Естественно, этой областью его применение не ограничивается.</p><p>Для этого случая помощник в виде процедуры от MS не нашёлся, поэтому пришлось использовать курсоры:</p><pre class="csharpcode"><span class="kwrd">declare</span> @pattern <span class="kwrd">as</span> nvarchar(<span class="kwrd">MAX</span>)<br /><span class="kwrd">set</span> @pattern = N<span class="str">'%Test%'</span><br /><span class="kwrd">set</span> nocount <span class="kwrd">on</span><br /><span class="kwrd">declare</span> @<span class="kwrd">sql</span> <span class="kwrd">as</span> nvarchar(<span class="kwrd">MAX</span>)<br /><span class="kwrd">declare</span> @<span class="kwrd">table</span> <span class="kwrd">as</span> sysname<br /><span class="kwrd">declare</span> tables <span class="kwrd">cursor</span> <span class="kwrd">local</span> <span class="kwrd">static</span> read_only <span class="kwrd">for</span> <span class="kwrd">select</span> name <span class="kwrd">from</span> sys.tables t <span class="kwrd">where</span> t.is_ms_shipped = 0<br /><span class="kwrd">open</span> tables<br /><span class="kwrd">fetch</span> <span class="kwrd">next</span> <span class="kwrd">from</span> tables <span class="kwrd">into</span> @<span class="kwrd">table</span><br /><span class="kwrd">create</span> <span class="kwrd">table</span> #results(name sysname <span class="kwrd">not</span> <span class="kwrd">null</span>, <span class="kwrd">value</span> nvarchar(<span class="kwrd">MAX</span>) <span class="kwrd">not</span> <span class="kwrd">null</span>)<br /><span class="kwrd">while</span> <span class="preproc">@@FETCH_STATUS</span> = 0<br /><span class="kwrd">begin</span><br /> <span class="kwrd">set</span> @<span class="kwrd">sql</span> = <span class="str">''</span><br /> <span class="kwrd">select</span> @<span class="kwrd">sql</span> = @<span class="kwrd">sql</span> + <span class="str">'<br /> insert into #results select '</span><span class="str">''</span> + @<span class="kwrd">table</span> + <span class="str">'.'</span> + name + <span class="str">''</span><span class="str">' as name, ['</span> + name + <span class="str">'] from ['</span> + @<span class="kwrd">table</span> + <span class="str">'] where ['</span> + name + <span class="str">'] like '</span><span class="str">''</span> + @pattern + <span class="str">''</span><span class="str">''</span><br /> <span class="kwrd">from</span> sys.columns c <span class="kwrd">where</span> c.object_id = OBJECT_ID(@<span class="kwrd">table</span>) <span class="kwrd">and</span> c.system_type_id <span class="kwrd">in</span> <br /> (<span class="kwrd">select</span> system_type_id <span class="kwrd">from</span> sys.types <span class="kwrd">where</span> collation_name <span class="kwrd">is</span> <span class="kwrd">not</span> <span class="kwrd">null</span>)<br /> <span class="kwrd">exec</span>(@<span class="kwrd">sql</span>)<br /> <span class="kwrd">fetch</span> <span class="kwrd">next</span> <span class="kwrd">from</span> tables <span class="kwrd">into</span> @<span class="kwrd">table</span><br /><span class="kwrd">end</span><br /><span class="kwrd">select</span> * <span class="kwrd">from</span> #results<br /><span class="kwrd">close</span> tables<br /><span class="kwrd">drop</span> <span class="kwrd">table</span> #results</pre><p>Помимо курсоров принципы те же. Есть пара нюансов:</p><ul><li>Ищем таблицы без флага is_ms_shipped, чтобы просматривать только таблицы, созданные на этапе разработки.</li><li>Для отбора строковых столбцов вместо списка типов (который поддерживать утомительно) используется фильтр "collation_name is not null".<br></li></ul><h2>Резюме</h2><p>Внимательный читатель наверняка догадался по оформлению, что последний пример написан не в то же время что и два первых. Если быть точнее, последний запрос я написал месяц назад. Это я к тому, что на основе подобного подхода вы можете сами писать полезные скрипты, решающие ваши специфические задачи.</p><p>Если такой формат понравится читателям, буду иногда выкладывать полезные скрипты из личной коллекции.</p><p><em>Если у вас есть замечания, пожелания или новые темы – пишите в комментариях, <a href="http://twitter.com/#!/OlegAxenow" rel="nofollow">твиттер</a> или на <a href="http://olegaxenow.reformal.ru/" rel="nofollow">olegaxenow.reformal.ru</a>. Постараюсь учесть.</em></p> Олег Аксёновhttp://www.blogger.com/profile/04146413181790640824noreply@blogger.com1tag:blogger.com,1999:blog-7309184816634381248.post-35033365469784844182012-02-08T23:20:00.001+04:002012-02-09T16:19:23.428+04:00Разработка пакетов NuGet + инфраструктура<p>
В <a title="Model scaffolding для MVC 3 – идеи и принципы (мой блог)" href="http://www.olegaxenow.com/2011/06/model-scaffolding-mvc-3-idei-i-principy.html" target="_blank">статье "Model scaffolding для MVC 3 – идеи и принципы"</a> я рассказал об идеях и принципах, заложенных в основу пакета <a title="Model Scaffolding (CodePlex)" href="http://modelscaffolding.codeplex.com/" rel="nofollow" target="_blank">Model Scaffolding</a>. Сейчас я расскажу о следующем:
<ul>
<li> Как написать простой пакет NuGet.</li>
<li> Как подготовить инфраструктуру для разработки и отладки пакетов NuGet.</li>
<li> Как <em>начать</em> реализовывать свой Scaffolder (генератор чего-либо в любом вашем проекте, необязательно ASP.NET MVC).</li>
</ul>
</p>
<p>
<strong>Важное замечание:</strong> после выхода NuGet 1.6 вы можете столкнуться с неожиданными ошибками при установке любых пакетов NuGet для Scaffolding (мои пакеты зависят от T4Scaffolding). В этом случае рекомендую такую последовательность:</p>
<ul>
<li>Uninstall NuGet.
<li>Install NuGet.
<li>Затем то же самое для всех Scaffolding-пакетов (с учетом зависимостей некоторые установятся сами).</li>
<h4>
NuGet</h4>
<p>
Scaffolder имеет смысл делать именно NuGet-пакетом, поэтому коротко расскажу о том что это и как создать и опубликовать пакет в простом случае (подробнее можно почитать в <a title="Creating and Publishing a Package (nuget.org)" href="http://docs.nuget.org/docs/creating-packages/creating-and-publishing-a-package" rel="nofollow" target="_blank">документации</a>). Про возможности NuGet я уже рассказывал раньше, в статье <a title="MVC 3 + scaffolding (мой блог)" href="http://www.olegaxenow.com/2011/05/mvc-3-scaffolding.html" target="_blank">MVC 3 + scaffolding</a>.</p>
<p>
NuGet-пакет формируется из набора файлов с помощью файла спецификации и приложения NuGet.exe. Затем его можно опубликовать на NuGet.org или на другом (например, своем) сервере. Также можно просто скопировать в некоторую папку, а папку добавить в настройки Visual Studio (Tools / Library Package Manager / Package Manager Settings). Так что, если хотите использовать возможности NuGet в своей закрытой разработке – это тоже возможно.</p>
</li></li></ul><a href="http://www.olegaxenow.com/2012/02/razrabotka-paketov-nuget-infrastruktura.html#more">Дальше »</a>Олег Аксёновhttp://www.blogger.com/profile/04146413181790640824noreply@blogger.com9tag:blogger.com,1999:blog-7309184816634381248.post-81870054553149460502012-01-15T22:56:00.001+04:002012-01-15T23:30:03.743+04:00Code First Migrations + Entity Framework 4.3 Beta 1<p><a href="http://lh5.ggpht.com/-5LqXoj5UUlM/TxMhQlWji2I/AAAAAAAAAbc/DiWwgG_J78g/s1600-h/MonarchButterfly2.jpg"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="MonarchButterfly" border="0" alt="MonarchButterfly" align="right" src="http://lh6.ggpht.com/-bqHcg-6gy7g/TxMhRDzeVMI/AAAAAAAAAbk/-KupQIlHQgU/MonarchButterfly_thumb.jpg?imgmax=800" width="244" height="164"></a>На днях, а точнее 12 января увидел свет <a title="EF 4.3 Beta 1 Released (ADO.NET team blog)" href="http://blogs.msdn.com/b/adonet/archive/2012/01/12/ef-4-3-beta-1-released.aspx" rel="nofollow" target="_blank">Entity Framework 4.3 Beta 1</a>. Основная тема этого релиза – EF Code First Migrations. Помимо этого, есть несколько изменений, которые тоже имеет смысл упомянуть.</p><p><em><font size="1">На фото миграция бабочки монарх (CC BY-NC-ND 2.0, оригинал </font></em><a title="Monarchs in motion (Flickr)" href="http://flic.kr/p/4RGhop" rel="nofollow" target="_blank"><em><font size="1">здесь</font></em></a><em><font size="1">).</font></em></p><p>В этой статье я, со своей точки зрения, разумеется, отвечу на вопросы, подкрепляя их примерами:</p><ul><li>Что такое миграции и для чего они нужны? <br>
<li>Что интересного в этом релизе и в EF Code First Migrations вообще?</li><br>
<p>Думаю, вряд ли кто-то использует миграции в повседневной коммерческой разработке. Поэтому я не буду явно выделять список нововведений, а буду просто рассказывать про миграции, отдельно выделяя новое в EF 4.3 Beta 1.</p><p>Кстати, наверное вам будет интересно, что релиз EF 4.3 планируется на <em>первый квартал этого года.</em> Жаль только что релиз EF 5.0 с поддержкой enum и оптимизированной скоростью ждёт наc нескоро – с выходом .NET 4.5 ожидается только EF 5.0 Beta 1.</p><h4></h4><h4>Краткое описание миграций</h4><p>Миграции в EF предназначены для решения проблемы изменения структуры базы данных в процессе эволюции приложения. Один из вариантов решения этой проблемы я озвучивал ранее в статье “<a title="Основы SQL - DDL и рефакторинг БД" href="http://www.olegaxenow.com/2011/01/osnovy-sql-ddl-i-refaktoring-bd.html" target="_blank">Основы SQL - DDL и рефакторинг БД</a>”. Надеюсь, что когда будет готов EF Code First Migrations, он будет значительно лучше, чем подход со скриптами.</p><p><strong>Важное замечание:</strong> основной момент, который нужно отслеживать при миграции базы данных вообще, помимо соответствия структуры, – сохранность клиентских данных.</p></li></ul><a href="http://www.olegaxenow.com/2012/01/code-first-migrations-entity-framework.html#more">Дальше »</a>Олег Аксёновhttp://www.blogger.com/profile/04146413181790640824noreply@blogger.com11tag:blogger.com,1999:blog-7309184816634381248.post-73938102120640165112012-01-09T18:46:00.001+04:002012-01-09T18:46:20.588+04:00Code Metrics + Refactoring<p><a href="http://lh6.ggpht.com/-2bzdO61vJiM/Twr9tcJKzmI/AAAAAAAAAa4/cLWufhxCbZc/s1600-h/Microscope2.jpg"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="Microscope" border="0" alt="Microscope" align="right" src="http://lh5.ggpht.com/-p8QXhnVUZ1U/Twr9t-pnLTI/AAAAAAAAAa8/SKIINfKbXuU/Microscope_thumb.jpg?imgmax=800" width="184" height="244"></a>Думаю, большинство из вас знают, что в Visual Studio есть набор метрик кода. Моя цель – привлечь к ним ваше внимание, в том числе как к одной из отправных точек для <strong>ревью кода и рефакторинга</strong>.</p> <p>Сначала я расскажу о запуске подсчёта метрик. Потом кратко опишу каждую метрику и дам некоторые рекомендации по рефакторингу в случае проблем. Затем немного расскажу о моём опыте использования метрик на практике.</p> <p>Однако, начиная разговор о метриках кода в Visual Studio, хочу пояснить моё отношение к метрикам кода вообще.</p> <p>С одной стороны, это мощный инструмент для оценки качества кода. По моему мнению, его обязательно стоит использовать как отправную точку для ревью кода (в том случае, когда идем не от коммита, а делаем ревью отдельного класса/модуля).</p> <p>С другой стороны, не стоит идеализировать метрики кода – это всего лишь один из инструментов. Вы же не считаете, что раз молоток хорошо забивает гвозди, это лучшее средство для закручивания шурупов? ;)</p> <a href="http://www.olegaxenow.com/2012/01/code-metrics-refactoring.html#more">Дальше »</a>Олег Аксёновhttp://www.blogger.com/profile/04146413181790640824noreply@blogger.com2tag:blogger.com,1999:blog-7309184816634381248.post-26686485084786450762012-01-08T00:34:00.001+04:002012-01-08T00:34:12.155+04:00Productivity Power Tools<p><img style="display: inline; float: right" align="right" src="http://i1.visualstudiogallery.msdn.s-msft.com/d0d33361-18e2-46c0-8ff2-4adea1e34fef/image/file/29669/12/screenshot.png">Если говорить о Productivity Power Tools нейтральным тоном, то это плагин к Visual Studio, который можно бесплатно <a title="Productivity Power Tools (Visual Studio Gallery)" href="http://visualstudiogallery.msdn.microsoft.com/d0d33361-18e2-46c0-8ff2-4adea1e34fef/" rel="nofollow" target="_blank">загрузить с Visual Studio Gallery</a>. Там же вы найдёте его описание на английском языке. Картинка оттуда же и хотя выглядит странно, однако, метафорически, так и есть – это не что иное как возможность “подкрутить” студию чтобы работать с ней было еще немного удобнее.</p> <p>Скажу сразу, весь набор возможностей (см. описание по ссылке выше) вам вряд ли понадобится. Однако одно я могу сказать наверняка – если вы используете студию без других дополнительных средств для навигации по коду и рефакторинга, то я очень удивлён, что вы читаете эти строки не закончив чтение на заголовке со словами “что о нём читать, и так всё знаю” :)</p> <p>Поэтому обладателям “чистой студии” рекомендую как минимум скачать этот плагин и попробовать. В результате наверняка пригодятся практически все предоставляемые возможности.</p> <p>Тем же, кто использует ReSharper и его альтернативы, вероятно будет интересно узнать, чем же меня “купил” плагин Productivity Power Tools. Сначала расскажу о двух “фишках” которые будут полезны многим, а потом о той, специфической, которая сильно повысила комфортность работы лично для меня. А в конце немного о других возможностях.</p> <h4></h4> <a href="http://www.olegaxenow.com/2012/01/productivity-power-tools.html#more">Дальше »</a>Олег Аксёновhttp://www.blogger.com/profile/04146413181790640824noreply@blogger.com13tag:blogger.com,1999:blog-7309184816634381248.post-14781605870357752862011-12-18T22:41:00.001+04:002011-12-18T22:52:38.419+04:00Отладка сессии ASP.NET<p><a href="http://lh4.ggpht.com/-l9K0PStqt-g/Tu4zzyMW7nI/AAAAAAAAAYY/03Hvu_aTONA/s1600-h/CrashTestDummy5.jpg"><img align="right" alt="CrashTestDummy" border="0" height="244" src="http://lh5.ggpht.com/-95GljRaU__w/Tu4z0ecZ3vI/AAAAAAAAAYg/KYpD-Wrs_TY/CrashTestDummy_thumb1.jpg?imgmax=800" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; float: right; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="CrashTestDummy" width="184"></a>На этот раз, как и обещал в статье “<a title="Сессия ASP.NET и проблема с параллельными запросами" href="http://www.olegaxenow.com/2011/11/sessiya-aspnet-i-problema-s.html" target="_blank">Сессия ASP.NET и проблема с параллельными запросами</a>”, я расскажу, как можно отладить обращения к сессии с помощью нестандартного провайдера.</p>
<p>А в завершение, в качестве бонуса, расскажу забавные подробности про режим ReadOnly, который иногда не совсем ReadOnly…</p>
<p>Для чего может потребоваться логгирование обращений к сессии? На мой взгляд, наиболее подходящими являются два сценария:</p>
<ul>
<li>“Нужно ускорить некоторые страницы нашего приложения, давайте посмотрим где используется сессия и нужна ли там запись в сессию или сессия вообще.”
<li>“Для того, чтобы не блокировать конкурентные запросы в рамках одной сессии, давайте прогоним все наши сценарии и проанализируем обращения к сессии.”</li>
</li></ul><a href="http://www.olegaxenow.com/2011/12/otladka-sessii-aspnet.html#more">Дальше »</a>Олег Аксёновhttp://www.blogger.com/profile/04146413181790640824noreply@blogger.com2tag:blogger.com,1999:blog-7309184816634381248.post-18707529526909234952011-11-27T15:06:00.001+04:002011-12-18T23:01:09.677+04:00Сессия ASP.NET и проблема с параллельными запросамиЭта статья будет интересна прежде всего тем, кто, явно или неявно, использует сессию ASP.NET в своих приложениях. Тем же, кто принципиально не использует сессию, можно почитать для общего развития – вдруг пригодится на будущее.<br>
<a href="http://lh6.ggpht.com/-IQE4axbcnsM/TtIZyMAXOJI/AAAAAAAAAYI/8zopDBwIOdM/s1600-h/mcdonalds_queue%25255B8%25255D.jpg"><img align="right" alt="mcdonalds_queue" border="0" height="139" src="http://lh4.ggpht.com/-06lIYv9YN7A/TtIZyvdP_EI/AAAAAAAAAYM/KHeRbT-ojUo/mcdonalds_queue_thumb%25255B2%25255D.jpg?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; float: right; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="mcdonalds_queue" width="244"></a><br>
И, поверьте мне, она будет невероятно интересна разработчикам таких приложений, которые могут обрабатывать несколько небыстрых одновременных запросов от одного пользователя. Показательный пример – одновременное скачивание нескольких больших файлов. Это реальная проблема, с которой столкнулись мои коллеги и на отладку которой было потрачено неадекватно много времени.<br>
<br>
Проблема состоит, в первую очередь, в неочевидности следующего факта: <strong>в рамках одной сессии (одного SessionID) параллельные запросы выполняются по очереди, если обработчики поддерживают сессию</strong>.<strong> </strong>При этом обращений к сессии в обработчике <strong>может не быть вообще </strong>– важна только поддержка сессии и её предварительная инициализация.<strong> </strong>В нашем примере это означает то, что пока не закачается один файл, закачивание других не начнется.<br>
<br>
В принципе, ситуация с конкурентными запросами в рамках <em>одной сессии</em> описана в статье MSDN <a href="http://msdn.microsoft.com/en-us/library/ms178581.aspx" rel="nofollow" target="_blank" title="ASP.NET Session State Overview (MSDN)">ASP.NET Session State Overview</a>. Но есть нюансы. Во-первых, это один неприметный абзац в конце статьи (вместо выделенного блока в начале). Во-вторых, MSDN не раскрывает многих неочевидных моментов. И, что важно, <strong>ни один из моих знакомых ASP.NET разработчиков не знал об этой особенности.</strong><br>
<br>
Заинтересовались? Тогда продолжаем. Я сформулирую несколько правил работы сессии и покажу на примере, что они верны.<br>
<a href="http://www.olegaxenow.com/2011/11/sessiya-aspnet-i-problema-s.html#more">Дальше »</a>Олег Аксёновhttp://www.blogger.com/profile/04146413181790640824noreply@blogger.com27tag:blogger.com,1999:blog-7309184816634381248.post-31847661996972063432011-10-13T01:31:00.001+04:002011-10-13T15:50:32.560+04:00ASP.NET MVC MiniProfiler<p>Всем доброго времени суток. Сегодня я хочу рассказать про <a title="ASP.NET MVC MiniProfiler" href="http://code.google.com/p/mvc-mini-profiler/" rel="nofollow" target="_blank">ASP.NET MVC MiniProfiler</a>. А первое, что я хочу рассказать, это то, что, вопреки распространённому мнению и названию, этот профайлер вполне можно применять для отладки обычных (не MVC) ASP.NET приложений. Дальше я на примере покажу как это сделать. А пока обо всем по порядку.</p> <h4>Что такое MiniProfiler?</h4> <p>Это способ отладить ASP.NET-приложение на production (или, если вам больше нравится, “приложение, находящееся в промышленной эксплуатации”). И, что важно, не сильно влияя на производительность (то, что это работает на сайтах платформы StackExchange как бы намекает).</p> <p>Вкратце процесс подключения выглядит так:</p> <ol> <li>Добавляется ссылка на dll. <li>Подключается в “Master Page” или любое другое подходящее место одна строчка по инициализации UI. <li>В Global.asax.cs прописываются вызовы по старту и остановке профайлера. <li>Либо добавляются вызовы Step(string) там, где вам интересно, либо “сбоку” добавляются фильтры (вроде ProfilingActionFilter), чтобы не модифицировать код.</li> <p>Опять же вкратце, на выходе получаем в виде небольшой разворачивающейся “закладки” на странице следующие возможности:</p> <ul> <li>Суммарное время. <li>Время на дочерние действия (пункт 4) и запросы к БД. <li>Показать/скрыть “тривиальные” запросы (с маленькими затратами времени). <li>Переслать ссылку на отчет (данные хранятся в кэше).</li> <p>Заинтересовались? Тогда продолжим…</p> </li></li></li></ul></li></li></li></ol><a href="http://www.olegaxenow.com/2011/10/aspnet-mvc-miniprofiler.html#more">Дальше »</a>Олег Аксёновhttp://www.blogger.com/profile/04146413181790640824noreply@blogger.com4tag:blogger.com,1999:blog-7309184816634381248.post-12723491595969362762011-09-29T23:24:00.001+04:002011-09-29T23:26:07.514+04:00Удобное и надежное хранение паролей<p><br>Всем доброго времени суток. После перегруза на работе и отпуска возвращаюсь к своему блогу. Чтобы не было резкого перехода ни для меня, ни для читателей, начну с небольшой заметки о моей инфраструктуре для хранения паролей. Сначала – небольшое лирическое отступление, а самые нетерпеливые могут пролистать до резюме.</p> <h4>История</h4> <p>Лет 15 назад паролей у меня было немного – интернет тогда еще не проник в мелкую бытовую технику :) Время шло, менялись работодатели, множились проекты, открывались новые нужные и ненужные сервисы… И лет 7 назад я понял, что держать важные пароли в голове мне надоело, даже учитывая их “генерацию” по определенным правилам. Альтернатива же использовать <em>одинаковые</em> пароли для разных сервисов была отметена задолго до этого :)</p> <a href="http://www.olegaxenow.com/2011/09/blog-post.html#more">Дальше »</a>Олег Аксёновhttp://www.blogger.com/profile/04146413181790640824noreply@blogger.com14tag:blogger.com,1999:blog-7309184816634381248.post-49136334127398785812011-06-16T00:19:00.004+04:002012-01-07T21:49:38.796+04:00Model scaffolding для MVC 3 – идеи и принципы<p>Эта статья является логическим продолжением статей <a title="ASP.NET MVC 3 + Entity Framework 4.1 Code First (мой блог)" href="http://www.olegaxenow.com/2011/05/aspnet-mvc-3-entity-framework-41-code.html" target="_blank">ASP.NET MVC 3 + Entity Framework 4.1 Code First</a>, <a title="MVC 3 + scaffolding (мой блог)" href="http://www.olegaxenow.com/2011/05/mvc-3-scaffolding.html" target="_blank">MVC 3 + scaffolding</a> и моей презентации на TechDays “<a title="Пример разработки сайта на MVC 3 (TechDays)" href="http://www.techdays.ru/videos/3618.html" rel="nofollow" target="_blank">Пример разработки сайта на MVC 3</a>”. В ней я расскажу про свой пакет для scaffolding’а <a title="Model Scaffolding for ASP.NET MVC (CodePlex)" href="http://modelscaffolding.codeplex.com/" target="_blank">Model Scaffolding for ASP.NET MVC</a>.</p> <p>Как я уже говорил ранее, идея написать этот пакет появилась после знакомства с проектом MvcScaffolding. Если вкратце, это пакет NuGet (минимальную необходимую информацию по NuGet и MvcScaffolding я привел в <a title="MVC 3 + scaffolding (мой блог)" href="http://www.olegaxenow.com/2011/05/mvc-3-scaffolding.html" target="_blank">предыдущей статье</a>), позволяющий быстро генерировать контроллеры и представления. Для первого знакомства с MvcScaffolding достаточно прочитать статьи автора “<a title="Scaffold your ASP.NET MVC 3 project with the MvcScaffolding package (Steve Sanderson’s blog)" href="http://blog.stevensanderson.com/2011/01/13/scaffold-your-aspnet-mvc-3-project-with-the-mvcscaffolding-package/" rel="nofollow" target="_blank">Scaffold your ASP.NET MVC 3 project with the MvcScaffolding package</a>” и “<a title="MvcScaffolding: Standard Usage (Steve Sanderson’s blog)" href="http://blog.stevensanderson.com/2011/01/13/mvcscaffolding-standard-usage/" rel="nofollow" target="_blank">MvcScaffolding: Standard Usage</a>”, а заинтересовавшимся после первого знакомства, рекомендую читать эту серию статей дальше.</p> <p>Для понимания дальнейшего изложения знакомство с MvcScaffolding не требуется, однако для более глубоко понимания потенциальных возможностей как MvcScaffolding так и ModelScaffolding оно будет весьма полезно. Далее я расскажу про ModelScaffolding по порядку, не забыв объяснить идеи и цели, которые лежат в его основе.</p> <h4>Disclaimer</h4> <p>Я не претендую на особую оригинальность и/или полезность своего подхода к scaffolding’у моделей. Я просто знаю, что есть круг задач которые он решает хорошо, а, на момент создания проекта на CodePlex, сходу не нашел аналога в рамках используемых технологий.</p> <p>К слову о “круге задач” – на мой взгляд, это прототипирование, причем необязательно “чистое прототипирование” (когда прототип гарантированно не будет использован в промышленной разработке). А самая идеальная задача – набор сущностей со стандартными названиями свойств и большим количеством простых справочников. К концу этой статьи вы поймете почему, а пока запаситесь терпением ;)</p> <a href="http://www.olegaxenow.com/2011/06/model-scaffolding-mvc-3-idei-i-principy.html#more">Дальше »</a>Олег Аксёновhttp://www.blogger.com/profile/04146413181790640824noreply@blogger.com2tag:blogger.com,1999:blog-7309184816634381248.post-14718600492862659942011-05-31T23:01:00.005+04:002012-01-07T21:49:38.792+04:00MVC 3 + scaffolding<p>А теперь обещанное продолжение статьи <a title="ASP.NET MVC 3 + Entity Framework 4.1 Code First (Мой блог)" href="http://www.olegaxenow.com/2011/05/aspnet-mvc-3-entity-framework-41-code.html" target="_blank">ASP.NET MVC 3 + Entity Framework 4.1 Code First</a>. Сегодня я расскажу про то, как <strong>быстро создать основу (или прототип)</strong> для приложения на ASP.NET MVC 3, в том числе, с помощью NuGet-пакета <a title="MvcScaffolding (CodePlex)" href="http://mvcscaffolding.codeplex.com/" rel="nofollow" target="_blank">MvcScaffolding</a>. Надо сказать, что принципы MvcScaffolding пришлись мне по душе и даже вдохновили меня на написание своего пакета для scaffolding’а - <a title="Model Scaffolding for ASP.NET MVC (CodePlex)" href="http://modelscaffolding.codeplex.com/" target="_blank">Model Scaffolding for ASP.NET MVC</a>. О нем я расскажу в следующих статьях.</p> <p>Поскольку в прошлой статье я уже рассказал про основные понятия и библиотеки (ASP.NET MVC, Entity Framework), сейчас я не буду на них подробно останавливаться. Пример будет использовать <strong>scaffolding</strong>, который я уже упоминал в предыдущий раз.</p> <p><strong>Disclaimer.</strong> Отмечу, что <em>scaffolding – это, вообще говоря, быстрая генерация чего-либо, с целью последующей доработки, а не способ быстро написать законченное сложное приложение.</em></p> <h4>NuGet</h4> <p>Пожалуй, единственное, на чем я забыл остановиться в прошлый раз, это <a title="NuGet (официальный сайт)" href="http://nuget.org/" rel="nofollow" target="_blank">NuGet</a>. Сама идея его не нова (apt-get, Ruby Gems и т.п.), однако то, что это теперь доступно и в Visual Studio очень радует. Следуя описанию с официального сайта:</p> <blockquote> <p>NuGet is a Visual Studio extension that makes it easy to install and update open source libraries and tools in Visual Studio.</p> </blockquote> <p>В принципе, добавить нечего, однако я все-таки немного добавлю :)</p>
<a href="http://www.olegaxenow.com/2011/05/mvc-3-scaffolding.html#more">Дальше »</a>Олег Аксёновhttp://www.blogger.com/profile/04146413181790640824noreply@blogger.com4tag:blogger.com,1999:blog-7309184816634381248.post-1905114567820572232011-05-11T00:25:00.003+04:002012-01-07T21:49:38.794+04:00ASP.NET MVC 3 + Entity Framework 4.1 Code First<p>Как вы все знаете, недавно вышло обновление MVC 3 Tools, ключевой особенностью которого является более продвинутый scaffolding. Кстати, scaffolding теперь есть и для движка <a title="ASP.NET MVC 3 + Razor (мой блог)" href="http://www.olegaxenow.com/2010/12/aspnet-mvc-3-razor.html" target="_blank">Razor</a>, что тоже плюс. Об этом, а также о недавнем обновлении Entity Framework я сегодня и расскажу. В этой статье речь пойдет про сами обновления, а в следующей будут примеры использования.</p> <p>Забегая вперед скажу, что scaffolding (по крайней мере, в случае ASP.NET MVC) это возможность быстро генерировать простую логику и интерфейс, которую можно использовать как прототип или в качестве отправной точки в дальнейшей разработке. Также этот подход может работать почти в чистом виде для простого административного интерфейса.</p> <h4>MVC (Model-View-Controller)</h4> <p>Наверняка, 99% читателей знают что такое MVC, однако, на всякий случай, расскажу очень коротко, а подробнее можно посмотреть в википедии (<a title="Model-View-Controller (википедия)" href="http://ru.wikipedia.org/wiki/Model-View-Controller" rel="nofollow" target="_blank">русскоязычной</a> или <a title="Model–view–controller (wikipedia)" href="http://en.wikipedia.org/wiki/Model–view–controller" rel="nofollow" target="_blank">англоязычной</a>) и приведенных в ней ссылках.</p> <p>MVC – это шаблон проектирования (хотя часто под ним подразумевают фреймворки, использующие этот шаблон). Основным принципом MVC является разделение ответственности между тремя составляющими:</p> <a href="http://www.olegaxenow.com/2011/05/aspnet-mvc-3-entity-framework-41-code.html#more">Дальше »</a>Олег Аксёновhttp://www.blogger.com/profile/04146413181790640824noreply@blogger.com12tag:blogger.com,1999:blog-7309184816634381248.post-28350034849691567242011-04-25T23:09:00.004+04:002011-05-05T19:52:05.472+04:00SQL – execution plan<p>Перейдя от <a title="Статьи с тэгом SqlIntro" href="http://www.olegaxenow.com/search/label/SqlIntro" target="_blank">рассказа про основы SQL</a> к более сложным вещам, я уже успел упомянуть план выполнения (execution plan). Чтобы не останавливаться на этой теме каждый раз, подробнее расскажу о нем в этой статье. Ведь это то, о чем многие разработчики, знакомые с Microsoft SQL Server не один год, либо не знают, либо не придают особого значения.</p> <p>Итак, сегодня я расскажу про такие вещи, как план выполнения и стоимость запроса; покажу на простых примерах как анализировать графический план выполнения; немного расскажу про подводные камни, связанные с планами выполнения; дам информацию для дальнейшего изучения.</p> <h4>План выполнения</h4> <p>Движку базы данных необходимо знать, в какой последовательности и каким способом соединять таблицы, какие индексы использовать и т.п. Иными словами, перед выполнением запроса необходимо построить (или взять из кэша) план выполнения.</p> <a href="http://www.olegaxenow.com/2011/04/sql-execution-plan.html#more">Дальше »</a>Олег Аксёновhttp://www.blogger.com/profile/04146413181790640824noreply@blogger.com17tag:blogger.com,1999:blog-7309184816634381248.post-26045089143351044272011-04-18T21:13:00.002+04:002011-04-18T21:15:52.121+04:00Трюки в SQL – используем CASE<p>После <a title="Статьи с тэгом SqlIntro" href="http://www.olegaxenow.com/search/label/SqlIntro" target="_blank">серии статей “Основы SQL”</a> я решил попробовать вспомнить некоторые нестандартные варианты использования Transact-SQL и начать серию статей “Трюки в SQL”.</p>
<p>В этой статье расскажу прежде всего о полезном но неочевидном использовании <a title="Выражение CASE (MSDN)" href="http://msdn.microsoft.com/ru-ru/library/ms181765.aspx" rel="nofollow" target="_blank">выражения CASE</a>. Правда, речь пойдет о достаточно простых приемах (когда их знаешь). Основное содержание:</p>
<ul>
<li><a href="http://www.olegaxenow.com/2011/04/tryuki-v-sql-ispolzuem-case.html#plan">План выполнения</a> </li>
<li><a href="http://www.olegaxenow.com/2011/04/tryuki-v-sql-ispolzuem-case.html#case">Синтаксис CASE</a> </li>
<li><a href="http://www.olegaxenow.com/2011/04/tryuki-v-sql-ispolzuem-case.html#sum">SUM по CASE</a> </li>
<li><a href="http://www.olegaxenow.com/2011/04/tryuki-v-sql-ispolzuem-case.html#order">ORDER по CASE</a> </li>
</ul>
<h4>База данных для примеров</h4>
<p>Если в прошлой серии я использовал максимально простую БД, которую создал и наполнил скриптами, то теперь я решил использовать стандартные примеры от Microsoft. Причина в том, что потребуются более сложные структуры и данные, да и примеры станут ближе к реальной жизни.</p>
<p>Поэтому для запуска примера потребуется БД AdventureWorks. Я пользовался <a title="AdventureWorks для SQL Server 2005 SP2a (CodePlex)" href="http://msftdbprodsamples.codeplex.com/releases/view/4004#DownloadId=11757" rel="nofollow" target="_blank">облегченной версией для Microsoft SQL Server 2005</a> (там, в зависимости от версии, можно выбрать AdventureWorksLT.msi или AdventureWorksLT_x64.msi). Скорее всего, подойдут и <a title="Sample Databases (CodePlex)" href="http://msftdbprodsamples.codeplex.com/" rel="nofollow" target="_blank">более поздние версии с CodePlex</a>.</p>
<a name="plan"></a>
<h4>План выполнения</h4>
<p>Расскажу на случай, если вы не знаете про план выполнения. В этой статьях этой серии он будет периодически упоминаться. Это пятилетний план выполнения… шутка, надеюсь вашим запросам никогда не придется так долго работать :)</p>
<a href="http://www.olegaxenow.com/2011/04/tryuki-v-sql-ispolzuem-case.html#more">Дальше »</a>Олег Аксёновhttp://www.blogger.com/profile/04146413181790640824noreply@blogger.com12tag:blogger.com,1999:blog-7309184816634381248.post-62883073449666442392011-04-18T13:47:00.009+04:002011-04-18T20:54:40.403+04:00Основы SQL – DML – SELECT – Часть III<p>В прошлый раз в этой <a title="Статьи с тэгом SqlIntro" href="http://www.olegaxenow.com/search/label/SqlIntro" target="_blank">серии статей</a> я рассказал об операторе “SELECT”, в том числе, для многотабличных запросов. Сейчас я продолжу эту тему, показав, как можно использовать группировку, и в завершении прикреплю скрипт для всех статей про “SELECT”.</p>
<p>Содержание:</p>
<ul>
<li><a href="http://www.olegaxenow.com/2011/04/osnovy-sql-dml-select-chast-iii.html#distinct">DISTINCT</a> </li>
<li><a href="http://www.olegaxenow.com/2011/04/osnovy-sql-dml-select-chast-iii.html#union">Объединения (UNION)</a> </li>
<li><a href="http://www.olegaxenow.com/2011/04/osnovy-sql-dml-select-chast-iii.html#group">Группировки (GROUP BY)</a> </li>
<li><a href="http://www.olegaxenow.com/2011/04/osnovy-sql-dml-select-chast-iii.html#stat">Статистические функции</a> </li>
<li><a href="http://www.olegaxenow.com/2011/04/osnovy-sql-dml-select-chast-iii.html#having">Фильтрация групп (HAVING)</a> </li>
<li><a href="http://www.olegaxenow.com/2011/04/osnovy-sql-dml-select-chast-iii.html#over">OVER, пейджинг и ранжирующие функции</a> </li>
<li><a href="http://www.olegaxenow.com/2011/04/osnovy-sql-dml-select-chast-iii.html#out">За кадром</a> </li>
<li><a href="http://www.olegaxenow.com/2011/04/osnovy-sql-dml-select-chast-iii.html#resume">Резюме</a> </li>
</ul>
<a name="distinct" id="distinct">
<h4>DISTINCT</h4>
</a>
<p>С помощью “DISTINCT” мы можем получить уникальные строки для практически любого запроса. Простейший пример, показывающий первые три цифры телефонных номеров:</p>
<div class="csharpcode-wrapper">
<pre id="codeSnippet" class="csharpcode"><span class="kwrd">SELECT</span> <span class="kwrd">DISTINCT</span> <span class="kwrd">LEFT</span>(Phone,3) <span class="kwrd">FROM</span> Phones</pre>
</div>
<p>Про использование “DISTINCT”, в силу его простоты, многого не скажешь. Однако, стоит сказать несколько слов про то, когда его использовать нежелательно. Предположим, нам необходимо получить список всех абонентов, у которых есть хотя бы один телефон. Теоретически, можно это сделать с помощью “DISTINCT”:</p>
<div id="codeSnippetWrapper" class="csharpcode-wrapper">
<pre id="codeSnippet" class="csharpcode"><span class="kwrd">SELECT</span> <span class="kwrd">DISTINCT</span> a.PersonID, a.LastName<br> <span class="kwrd">FROM</span> Persons a <span class="kwrd">JOIN</span> Phones t <span class="kwrd">ON</span> a.PersonID = t.PersonID</pre>
</div>
<p>Однако в данном случае правильнее использовать конструкцию “WHERE EXISTS”:</p>
<div id="codeSnippetWrapper" class="csharpcode-wrapper">
<pre id="codeSnippet" class="csharpcode"><span class="kwrd">SELECT</span> a.PersonID, a.LastName<br> <span class="kwrd">FROM</span> Persons a<br> <span class="kwrd">WHERE</span> <span class="kwrd">EXISTS</span>(<span class="kwrd">SELECT</span> * <span class="kwrd">FROM</span> Phones t <span class="kwrd">WHERE</span> a.PersonID = t.PersonID)</pre>
</div>
<a href="http://www.olegaxenow.com/2011/04/osnovy-sql-dml-select-chast-iii.html#more">Дальше »</a>Олег Аксёновhttp://www.blogger.com/profile/04146413181790640824noreply@blogger.com5tag:blogger.com,1999:blog-7309184816634381248.post-63541395312133765452011-03-29T23:18:00.003+04:002011-03-31T14:56:24.399+04:00Основы SQL – DML – SELECT – Часть II<p>В прошлый раз в этой <a title="Статьи с тэгом SqlIntro" href="http://www.olegaxenow.com/search/label/SqlIntro" target="_blank">серии статей</a> я рассказал об операторе “SELECT” в самом простом его проявлении – запросы к одной таблице, без сложных фильтров. Теперь я расскажу о более интересной, но сложной теме – многотабличных запросах.</p>
<p>Также, в завершении статьи, я дам несколько полезных рекомендаций, предотвращающих превращение поддержки многотабличных запросов в постоянную головную боль.</p>
<h4>Многотабличные запросы без JOIN</h4>
<p>Хотя в более ранних версиях Microsoft SQL Server многотабличные запросы без “JOIN” были более распространены, теперь они используются все реже и реже. И это, с моей точки зрения, правильно. Использование “JOIN” приводит, как минимум, к более структурированному и читаемому коду (что мы увидим чуть позже), а на символах в исходном коде я никогда не экономил :)</p>
<p>Самый простой вариант многотабличного запроса – это двухтабличные запрос без условия соединения таблиц или <a title="декартово (прямое) произведение (википедия)" href="http://ru.wikipedia.org/wiki/Прямое_произведение" rel="nofollow" target="_blank">декартово произведение</a> таблиц. И это, пожалуй, единственный вариант, когда от отсутствия “JOIN” не страдает наглядность:</p>
<div id="codeSnippetWrapper" class="csharpcode-wrapper">
<pre id="codeSnippet" class="csharpcode"><span class="kwrd">SELECT</span> * <span class="kwrd">FROM</span> Persons, Phones</pre>
</div>
<a href="http://www.olegaxenow.com/2011/03/osnovy-sql-dml-select-chast-ii.html#more">Дальше »</a>Олег Аксёновhttp://www.blogger.com/profile/04146413181790640824noreply@blogger.com3tag:blogger.com,1999:blog-7309184816634381248.post-66195543432719654782011-03-19T23:37:00.003+03:002011-03-29T23:20:16.428+04:00Основы SQL – DML – SELECT – Часть I<p>Продолжаю <a title="Статьи с тэгом SqlIntro" href="http://www.olegaxenow.com/search/label/SqlIntro" target="_blank">серию статей “Основы SQL”</a>. В этой статье я расскажу про сравнительно простые варианты применения самого сложного оператора DML – SELECT. Если в начале статьи дать полный синтаксис SELECT – это будет серьезным поводом загрустить и не читать статью дальше, поэтому я буду рассказывать про возможности этого оператора постепенно :)</p>
<h4>Простейший случай</h4>
<p>Позволю себе немного дополнить <a title="SELECT (MSDN)" href="http://msdn.microsoft.com/ru-ru/library/ms189499(v=SQL.105).aspx" rel="nofollow" target="_blank">статью MSDN о SELECT</a> тем, что данный оператор может использоваться не только для "выборки одной или нескольких строк или столбцов из одной или нескольких таблиц", но и для получения набора данных, не имеющего в своей основе ни одной таблицы:</p>
<div id="codeSnippetWrapper" class="csharpcode-wrapper">
<pre id="codeSnippet" class="csharpcode"><span class="kwrd">SELECT</span> 1 <span class="kwrd">AS</span> ID, <span class="str">'Test 1'</span> <span class="kwrd">AS</span> Name</pre>
</div>
<p>Разумеется, в итоге результат выглядит как выборка из некоторой таблицы (если мы не будем использовать специальные конструкции для получения результата в виде XML).</p>
<p>Если одной строки недостаточно, можно использовать несколько запросов, объединенных с помощью UNION ALL. Если не использовать “ALL” в этой конструкции, в результате гарантированно не будет дублирующихся строк. Это тоже бывает полезно, но, если вы точно знаете, что дубликатов и так не будет, лучше использовать “UNION ALL”, чтобы уменьшить накладные расходы.</p>
<a href="http://www.olegaxenow.com/2011/03/osnovy-sql-dml-select-chast-i.html#more">Дальше »</a>Олег Аксёновhttp://www.blogger.com/profile/04146413181790640824noreply@blogger.com2tag:blogger.com,1999:blog-7309184816634381248.post-62566119797844364432011-03-14T09:15:00.003+03:002011-03-14T16:07:35.585+03:00Облачные хранилища файлов – личный опытРешил, для разнообразия, написать на тему организации рабочего места. Наверняка у многих есть потребность в хранении и синхронизации файлов с помощью, как это модно сейчас говорить, облачного хранилища. Речь не про Azure и иже с ним, а про такие сервисы хранения файлов как DropBox, SkyDrive и т.п.<br>
<br>
Лично я использую их для синхронизации своих заметок, паролей (естественно, зашифрованных), полезных SQL-скриптов и т.п. Удобно иметь актуальные версии и дома, и на работе и в смартфоне.<br>
<br>
В этой короткой статье расскажу про свой местами многолетний, а местами практически нулевой опыт работы с некоторыми из них. Если кто-то дополнит пробелы в моих знаниях, буду премного благодарен.<br>
<a href="http://www.olegaxenow.com/2011/03/oblachnye-hranilischa-failov-lichnyi.html#more">Дальше »</a>Олег Аксёновhttp://www.blogger.com/profile/04146413181790640824noreply@blogger.com4tag:blogger.com,1999:blog-7309184816634381248.post-15759470187498357692011-01-28T22:40:00.004+03:002011-03-29T23:20:16.428+04:00Основы SQL – DML – DELETEПродолжаю серию статей “Основы SQL”. В предыдущих сериях:
<br>
<ul>
<li><a href="http://www.olegaxenow.com/2011/01/osnovy-sql-pervoe-znakomstvo.html" target="_blank" title="Основы SQL - первое знакомство">Первое знакомство</a> </li>
<li><a href="http://www.olegaxenow.com/2011/01/osnovy-sql-ddl-i-refaktoring-bd.html" target="_blank" title="Основы SQL - DDL и рефакторинг БД">DDL и рефакторинг БД</a> </li>
<li><a href="http://www.olegaxenow.com/2011/01/osnovy-sql-dml-insert-i-drugie.html" target="_blank" title="Основы SQL – DML – INSERT и другие">DML – INSERT и другие</a> </li>
<li><a href="http://www.olegaxenow.com/2011/01/osnovy-sql-dml-update.html" target="_blank" title="Основы SQL – DML – UPDATE">DML – UPDATE</a> </li>
</ul>
В этой статье я завершу рассказ про операторы DML, изменяющие данные - речь пойдет про DELETE – оператор, с помощью которого можно удалить одну или много строк в таблице, или много строк во многих таблицах… главное – не слишком увлекаться :)
<br>
<h4>
Удаление строк</h4>
Удаление строк более простая операция чем все остальные в DML, по большому счету, все сказанное относительно <a href="http://www.olegaxenow.com/2011/01/osnovy-sql-dml-update.html" target="_blank" title="Основы SQL – DML – UPDATE">UPDATE</a> применимо и к DELETE, с той лишь разницей, что данные удаляются, а не модифицируются, и синтаксис немного другой:<br>
<div class="csharpcode-wrapper" id="codeSnippetWrapper">
<pre class="csharpcode" id="codeSnippet"><span class="kwrd">DELETE</span> Phones <span class="kwrd">WHERE</span> PersonID = 1 <span class="kwrd">AND</span> Phone = <span class="str">'100-1'</span></pre>
</div>
В этом примере происходит удаление одной строки (если такая есть), потому что, как вы помните, “PersonID” и “Phone” являются составным первичным ключом.
<br>
<br>
<a href="http://www.olegaxenow.com/2011/01/osnovy-sql-dml-delete.html#more">Дальше »</a>Олег Аксёновhttp://www.blogger.com/profile/04146413181790640824noreply@blogger.com7tag:blogger.com,1999:blog-7309184816634381248.post-66811741437706548202011-01-27T23:09:00.005+03:002011-03-29T23:20:16.429+04:00Основы SQL – DML – UPDATEПродолжаю серию статей “Основы SQL”. В предыдущих сериях:
<br>
<ul>
<li><a href="http://www.olegaxenow.com/2011/01/osnovy-sql-pervoe-znakomstvo.html" target="_blank" title="Основы SQL - первое знакомство">Первое знакомство</a> </li>
<li><a href="http://www.olegaxenow.com/2011/01/osnovy-sql-ddl-i-refaktoring-bd.html" target="_blank" title="Основы SQL - DDL и рефакторинг БД">DDL и рефакторинг БД</a> </li>
<li><a href="http://www.olegaxenow.com/2011/01/osnovy-sql-dml-insert-i-drugie.html" target="_blank" title="Основы SQL – DML – INSERT и другие">DML – INSERT и другие</a> </li>
</ul>
В прошлый раз я немного рассказал про оператор INSERT (куда же без него – без первоначальных данных применять остальные операторы DML не имеет смысла).
<br>
Сейчас речь пойдет про UPDATE – оператор, позволяющий модифицировать существующие данные.
<br>
<h4>
Модификация одной строки</h4>
Если для оператора INSERT существует разный синтаксис для вставки одной строки и множества строк, то для UPDATE синтаксис одинаковый и в простейшем случае выглядит так:<br>
<div class="csharpcode-wrapper" id="codeSnippetWrapper">
<pre class="csharpcode" id="codeSnippet"><span class="kwrd">UPDATE</span> Persons <span class="kwrd">SET</span> LastName = <span class="str">'Петров'</span> <span class="kwrd">WHERE</span> PersonID = 1</pre>
<pre class="csharpcode" id="codeSnippet"></pre></div><a href="http://www.olegaxenow.com/2011/01/osnovy-sql-dml-update.html#more">Дальше »</a>Олег Аксёновhttp://www.blogger.com/profile/04146413181790640824noreply@blogger.com0