-->

понедельник, 24 августа 2015 г.

WcfStorm - тестовый WCF клиент на стероидах



В этом посте я поделюсь радостью от использования замечательной утилиты WcfStorm. Но, обо всем по-порядку.
Многие, работающие с WCF, сталкиваются с задачей оперативного тестирования веб-сервисов. Конечно, запустить Visual Studio, сгенерировать прокси и написать пару тестовых методов - это беспроигрышный вариант, но при работе с десятками сервисов такой подход грозит огромными потерями времени. Да и Студии в нужный момент может просто не быть под рукой.
Microsoft предлагает использовать для подобных задач программу WcfTestClient, входящую в состав Visual Studio, но целый ряд функциональных ограничений не позволяет использовать эту утилиту в реальных проектах. К примеру, на моем текущем проекте используются HTTPS привязки, а также авторизация через логин/пароль - и всё это не поддерживается в WcfTestClient! Да и по уровню usability эта утилита находится на уровне студенческой поделки.

То ли дело WcfStorm:

  • поддержка всех привязок, кроме webHttp;
  • поддержка Security;
  • дружественный UI;
  • сохранение/загрузка конфигураций;
  • нагрузочные тесты и многое другое!

При всем этом использовать утилиту очень просто: вбиваешь ссылку - клиент готов к работе. Долой рутину! WcfStorm высвобождает время разработчика для более важных дел. Советую попробовать каждому, работающему с WCF.

суббота, 22 августа 2015 г.

Exception.ToString() - в чем твоя проблема?

Сегодня я бы хотел поделиться своей болью: архитектурный изъян в реализации метода Exception.ToString() приводит к потере части информации для некоторых вложенных  исключений. Всем известно, что данный метод выводит Message + StackTrace самого исключения и всех вложенных. Например, следующий код:
var exception = new FileNotFoundException("error message", "filename");

Console.WriteLine(exception.ToString());
Выведет на консоль:
System.IO.FileNotFoundException: error message
File name: 'filename'
Теперь вложим наше исключение в другое:
var exception = new FileNotFoundException("error message", "filename");

var outerException = new Exception("outer message", exception);

Console.WriteLine(outerException.ToString());
Результат:
System.Exception: outer message ---> System.IO.FileNotFoundException: error message
 --- End of inner exception stack trace --- 
Заметили? Где имя пропавшего файла?

среда, 19 августа 2015 г.

Шаблоны Т4 - генерация любого текста (кода) в Visual Studio

На днях возникла потребность автоматизировать одну рутинную, регулярную задачу в рабочем проекте, суть которой сводится к генерации новых классов по уже имеющимся и написании методов-оберток для имеющихся методов по одному и тому же шаблону. Первый подход, который пришел в голову - это генерация кода посредством Т4-шаблонов в Visual Studio.  Пригодность подхода оценивалась по следующему тестовому заданию:
Имеется пространство имен (без вложенных подпространств), в котором находится ряд классов (и, возможно, других типов). На основе набора публичных свойств каждого класса, необходимо сгенерировать соответствующие классы-DTO. Типы свойств могут быть как встроенными типами CLR, так и классами из этого же пространства имен.
Грубо говоря, генерируем DTO по каждому заданному классу. С помощью Reflection с последующим выводом на консоль, задача решается за чашку чая. Перенести готовый код в *.tt файл тоже нетрудно - в данном случае, достаточно заменить вызовы Console на соответствующие вызовы класса GeneratedTextTransformation (о нем чуть ниже), а также прописать в *.tt файле все используемые сборки и пространства имен.

суббота, 8 августа 2015 г.

Optimistic concurrency в EF + SQL Server

К написанию этого поста меня подтолкнуло большое количество гайдов по Entity Framework, в которых задача реализации оптимистического конкурентного доступа (бррр! далее просто optimistic concurrency) сводится к добавлению столбца с типом rowversion (timestamp) в БД, либо использованию атрибута ConcurrencyCheck на интересующих полях класса. Идея такого подхода достаточно проста: выбранные поля будут включены в раздел WHERE инструкции UPDATE. Зачем? Рассмотрим простейший случай:

Получение данных из БД -> Изменение данных -> Сохранение в БД.

Если между загрузкой и сохранением данные в БД были изменены другим потоком/процессом, EF сможет определить конфликт, сравнив версии строк таблицы (если используется rowversion) либо попарно сравнив значения свойств, помеченных ConcurrencyCheck. В результате мы получим исключение, а данные в БД сохранены не будут. Причем, даже объявлять транзакцию в явном виде не нужно (хорошая идея, ага).

Это здорово - иметь optimistic concurrency из коробки, и формально не зависящее от БД. Но будем откровенны: наиболее популярное СУБД в одной упряжке с EF - это SQL Server, а процент проектов, где смена СУБД допускается хотя бы в перспективе - исчезающе мал. Так почему бы не воспользоваться средствами SQL Server? Конечно же, я говорю об уровнях изоляции SNAPSHOT и READ COMMITTED SNAPSHOT. У меня бы не получилось рассказать об изоляции транзакций лучше, чем у авторов моей любимой Microsoft SQL Server 2012 Internals, поэтому не буду и пытаться. Попробуем сравнить подходы EF и SQL Server к реализации optimistic concurrency.

воскресенье, 26 июля 2015 г.

Заметки на полях: конкурентный доступ в SQL Server

Полагаю, многие разработчики, потратив кучу времени на изучение и систематизацию определенной области знаний, оставляют заметки со списком полезных источников и своими комментариями. И я не исключение. Бывает так, что поставленная проблема разрешена, и применение накопленных знаний какое-то время не требуется. Поэтому такие заметки сильно помогают при необходимости быстро освежить свои знания, когда различные детали и тонкости реализации уже выветрились из кратковременной памяти. Дабы повысить качество подобных записей - я решил попробовать публиковать их. Теперь просто накидать десяток ссылок в Evernote и забыть про них не получится. Надеюсь, заметки перестанут теряться среди сотен других и забываться, а я не буду лениться их делать.
Тема, с которой я хотел бы начать - это уровни изоляции транзакций, блокировки, и pessimistic/optimistic concurrency в SQL Server (нет, я не DBA и не планирую им быть). Attention! Все ниже перечисленное - относится не к книгам целиком, а только лишь к их соответствующим разделам по конкурентному доступу.


Ицик Бен-Ган. Microsoft SQL Server 2008/2012. Основы T-SQL
Принципиальных различий между книгами этого автора для 2008 и 2012 SQL Server немного. Для книг Ицика Бен-Гана характерен легкий, удобочитаемый стиль изложения. Различия уровней изоляции показаны на простейших примерах, для выполнения которых достаточно SSMS. В то же время, информация в книге дана скудная и неполная - например, не рассмотрен update lock. Пожалуй, с этой книжной серии можно начинать знакомство с concurrency в SQL Server, но для знакомых с темой людей она почти бесполезна.


Душан Петкович. Microsoft SQL Server 2012. Руководство для начинающих
В разы больше информации о блокировках. Примеры далеко не так информативны и понятны, в том числе из-за постоянного использования инструкции WAITFOR. В целом уровень изложения чуть выше.

Kalen Delaney. Microsoft SQL Server 2012 Internals
Если первые 2 книги - руководства для начинающих, то вот этот монументальный труд не стыдно прочитать разработчику любого уровня. Самое подробное и всеобъемлющее руководство из тех, что я видел. Держу оригинал книги под рукой в качестве справочника. Стиль изложения объемный и многословный.
Кому чтение книги по каким-то причинам не подходит, могу посоветовать статью от той же Kalen Delaney, содержание в целом соответствует стилю, выдержанному в книге. Там же я узнал, что у Delaney не так давно вышла отдельная книга, посвященная блокировкам в SQL Server:
При этом книжка бесплатная и доступна для скачивания в электронном виде! Да это просто праздник какой-то! Книга так же информативна, как и ее "старшая сестра", держу экземпляр под рукой.

И конечно, не будем забывать про официальную документацию.
TechNet: Locking and Row Versioning
Еще я планировал добавить ворох ссылок на различные мануалы по concurrency с codeproject, хабра и подобных сайтов. Отказался от этой идеи после очередного прочтения  Microsoft SQL Server 2012 Internals. Еще раз всем рекомендую почитать и напоминаю, что я кое-как сравнил между собой только посвященные конкурентному доступу материалы в этих книгах - в районе 1 главы из каждого источника. Удачи!


пятница, 10 июля 2015 г.

AutoMapper: internal properties mapping

Ранние версии AutoMapper умели производить маппинг только публичных свойств классов. Ситуация изменилась в версии 3.3.0 - появилась долгожданная возможность мапить не только public, но и internal свойства путем указания перечисления BindingFlags:
Mapper.Initialize(cfg =>
{
   cfg.BindingFlags = 
      BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
});
К несчастью, эта фича вновь стала недоступна в версии 3.3.1. По словам автора - так как возникли проблемы с реализацией под все платформы. Есть вероятность, что BindingFlags вернутся в следующих версиях AutoMapper. Обсуждение на GitHub.

четверг, 9 июля 2015 г.

AutoMapper: хитрости

Вольный сокращенный перевод понравившегося поста с CodeProject. Рассматриваемые темы:

1. Projection
2. Configuration Validation
3. Custom Conversion
4. Value Resolvers
5. Null Substitution


В отличие от автора, я бы поставил Configuration Validation на первое место по важности. Проверка соответствия свойств класса-результата и класса-источника гарантирует, что любые опечатки, переименования и просто несоответствия имен не останутся незамеченными. Маппинг становится прозрачным и предсказуемым. Но обо всем по порядку:

воскресенье, 5 июля 2015 г.

О переводах и подсознательном

Для разнообразия (не все же время кодить), я перевел пару интересных статей из своей RSS-ленты. Запостил на Хабр, как обычно:

О собеседованиях (от Эрика Липперта)
Гуру C# и просто увлекательный рассказчик, Эрик Липперт объясняет, как собеседует кандидатов на работу, на что обращает внимание и зачем задает те или иные вопросы.

Неразбериха с названиями должностей
Рассуждения сотрудника Stack Exchange о весьма слабой связи между званием (Junior, Senior, Lead и т.п.) и реальными опытом и способностями программиста. Что меняется в жизни Team Lead с большим опытом, если он устраивается на должность Developer.

Обе статьи затрагивают тему технических собеседований, одна с точки зрения интервьюера, другая - с точки зрения соискателя. Мне казалось, что я выбрал статьи случайно, но теперь думаю, что мое подсознание пытается что-то сказать =) И вправду, в рабочие часы сейчас происходит слишком мало интересного. 95% времени уходит на и так хорошо мне знакомые вещи, при этом нагрузка большая, и ни на что другое времени не остается. А жаль, текущий проект - непаханое поле для оптимизации, рефакторинга и различных архитектурных улучшений.

пятница, 3 июля 2015 г.

Преобразования конфигурационных файлов. Новая схема



Трюк из моего старого поста, позволяющий трансформировать Web.config при локальной сборке проекта в зависимости от выбранной конфигурации - активно используется на текущем проекте и уже сэкономил команде многие часы работы. Мы используем 5+ конфигураций (Debug, Test, Release, PreRelease и т.п.) для удобного переключения в 5 точках входа между десятком внешних сервисов, 5-6 версиями одной БД, различными оптимизационными настройками и т.п.

Можно ли эту схему упростить еще больше? В некоторых случаях - да, можно.

пятница, 5 июня 2015 г.

Соглашения по оформлению кода C#

Недавно наша команда приняла соглашение по оформлению кода, в составлении и продвижении которого я принимал непосредственное участие. Мы не стали изобретать велосипед и взяли за основу соглашения от команды RSDN, дополнив их. Надеюсь, теперь в рабочем коде будет чуть меньше хаоса. Ниже приводится текст принятого документа (чуть съехала верстка):

суббота, 30 мая 2015 г.

Баг в Entity Framework - дублирование строк при запросе к SQL VIEW

При выборке из View часть строк дублируется и отличается от результата, возвращаемого SQL Server. Ошибка не нова и связана с тем, что View не содержит столбцов, позволяющих однозначно идентифицировать каждую строку, либо EF не может самостоятельно распознать такие столбцы. Легко лечится. Итак, обо всем по порядку.

воскресенье, 24 мая 2015 г.

Паттерны Repository и Unit of Work для Entity Framework

По моим впечатлениям, по архитектуре использующих Entity Framework приложений написано куда больше плохих примеров и гайдов, чем хороших. Кто-то не брезгует передачей entities через все слои приложения прямо в UI, кто-то борется с заложенной в EF архитектурой, реализуя свое видение паттернов из книг по дизайну. О последних и пойдет речь. Хит-парад паттернов с приставкой "анти-" возглавляют свои реализации Generic Repository.

вторник, 12 мая 2015 г.

Хабрахабр, ORM и прочие радости

Недавно я стал кандитатом технических наук. Надеюсь, теперь времени на блог будет больше, и он заживет нормальной жизнью. 

Также я закончил материал по OrmLite и выложил сразу на Хабре: 
Содержание статьи:

  • Подготовка к работе. Code-first и database-first подходы
  • Запросы к БД
  • JOIN и navigation properties
  • Lazy и Async
  • Транзакции
  • Сравнение производительности OrmLite и Entity Framework

Наконец, 2 моих старых поста (раздва) об использовании SqlBulkCopy совместно с Entity Framework для повышения производительности - еще весной были переработаны для Хабра, получилась одна большая статья:
Содержание статьи:

  •  Insert/Update стандартными средствами Entity Framework
  •  Entity Framework и SqlBulkCopy
  •  Продвинутая вставка с использованием MERGE
  •  Сравнение производительности

На данный момент план такой: Хабрахабр для объемных технических статей, блог - для подготовительных исследований, рецептов, заметок "на полях".

понедельник, 16 марта 2015 г.

Entity Framework: рецепты повышения производительности

У меня была идея написать большой сборник рекомендаций по улучшению производительности запросов к БД для Entity Framework, собрать воедино best practices из различных источников и поделиться собственными наблюдениями.

пятница, 6 марта 2015 г.

Преобразование Web.config при сборке веб-приложения

Всем известно, что Visual Studio позволяет изменить содержимое файла Web.config развертываемого приложения в зависимости от используемой конфигурации. При сборке (build) преобразование не выполняется, что не всегда удобно. В этом посте я покажу, как включить преобразование Web.сonfig при локальной сборке проекта.

пятница, 27 февраля 2015 г.

Генерация документов (DOC, HTML) из HTML-шаблона с использованием RazorEngine

Задача: генерировать юридические документы и письма-уведомления из html-шаблонов. Разметка в шаблонах несложная: в рамках тегов <b>, <i>, <table>. Однако, документы могут быть достаточно объемными (~10 стр.).

среда, 18 февраля 2015 г.

Оптимизация Entity Framework: Update


Обновление записей штатными средствами Entity Framework приводит к генерации UPDATE команды на каждую запись (как и в случае со вставкой записей в БД). В случае единовременного обновления тысяч записей, стандартный EF подход приводит к ощутимому падению производительности. Все нижеописанное верно в первую очередь для Entity Framework 5-6 (POCO + Database First) и SQL Server 2008 и выше. Изучим проблему подробнее.

вторник, 3 февраля 2015 г.

Оптимизация Entity Framework: Insert

Введение

Вставка большого количества записей в базу данных с помощью Entity Framework выполняется очень медленно. Причиной этому являются как архитектурные особенности самого фреймворка, так и неоптимальный генерируемый SQL. В данной статье я рассмотрю различные пути решения данной проблемы. Все описанное верно в первую очередь для Entity Framework 5-6 (POCO + Database First) и SQL Server 2008 и выше.

План статьи:
  1. INSERT стандартными средствами Entity Framework
  2. Поиск решения. SqlBulkCopy
  3. Интеграция Entity Framework и SqlBulkCopy
  4. Замеры производительности
  5. Выводы
  6. Что почитать