-->

понедельник, 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.