Недавно (в июле этого года) вышла новая версия MS Sql CE, в которой был изменен алгоритм шифрования (стал использоваться SHA-2). Это означает, что для работы sql ce 4 с бд, созданной сервером версии 3.5, ее нужно предварительно переконвертировать. Для это в API предусмотрен специальный метод, поэтому особого труда конвертирование не вызовет.
Давайте напишем конвертер для файлов баз данных в формате slq ce 3.5 в формат slq ce 4.0.
Писать будем на C# в TDD-стиле, использовать VS 2008, тестировать в xUnit (последнюю версию можно скачать с codeplex). Когда вы используете TDD, не нарушая основных принципов ( а их всего три - RGR (красный-зеленый-синий): пишем тест, пишем код, рефакторим) и порядка их следования, то получаете автоматически приятные бонусы в коде.
Warning! Этот пост нужно рассматривать как пример по разработке в стиле TDD для начинающих.
Итак, начнем. Создаем новый Windows Forms Application - проект в VS (у меня он называется "SqlCE3.5_to_4.0"), сразу же добавляем в солюшн еще один проект Class Library, называем его Tests. И, в лучших традициях TDD, начинаем писать наш первый тест.
public class SqlCEVersionConverterTests
{
[Fact]
public void ConvertTest()
{
string file2convert = @"C:\sqlCE35.sdf";
var sqlCEConverter = new SqlCEVersionConverter(file2convert);
Assert.True(sqlCEConverter.Convert());
}
}
Так я представляю себе работу нашего конвертера. Тест, конечно же, не срабатывает - ведь класс SqlCEVersionConverter не реализован. Этим и займемся. Добавим в главный проект новый класс, SqlCEVersionConverter. Пока нам нужно сделать минимум телодвижений, чтобы заставить тест сработать - делаем фейковую реализацию:
public class SqlCEVersionConverter
{
public SqlCEVersionConverter(string file2convert)
{
}
public bool Convert()
{
var result = true;
return result;
}
}
Запускаем тест... Ура! Тест сработал. Теперь посмотрим, что нам нужно для того, чтобы метод Convert() заработал по-настоящему. Нам нужно подключиться к выбранной базе данных и заапгрейдить ее.
public bool Convert()
{
var result = false;
using (SqlCeEngine sqlCeEngine = new SqlCeEngine(connectionString))
{
try
{
sqlCeEngine.Upgrade();
result = true;
}
catch (Exception e)
{
//обработка исключения
}
}
return result;
}
Код не компилируется (F6) - не хватает строки соединения (connectionString). Добавляем новое поле в класс. Теперь код компилируется, но тест не срабатывает - мы используем пустую connectionString, из-за чего и не можем подключиться к БД, чтобы переконвертировать ее. Значит, нам нужен метод, который бы создавал строку подключения. Настало время писать следующий тест.
[Fact]
public void BuildConnectionStringTest()
{
string sqlCEdbFile = @"C:\sqlCE35.sdf";
var converter = new SqlCEVersionConverter(file2convert);
string connectionString = converter.BuildConnectionString(sqlCEdbFile);
Assert.Equal(@"Data Source=C:\sqlCE35.sdf;Mode=Exclusive", connectionString);
}
Код не компилируется, нужно реализовать метод BuildConnectionString():
public string BuildConnectionString(string sqlCEdbPath)
{
SqlCeConnectionStringBuilder builder = new SqlCeConnectionStringBuilder();
builder["Data Source"] = sqlCEdbPath;
builder["Mode"] = "Exclusive";
return builder.ConnectionString;
}
В реализации этого метода мы сразу опробовали новый API slq ce 4 - класс SqlCeConnectionStringBuilder.
Ничего так, удобненько :)
Теперь изменим конструктор SqlCEVersionConverter:
public SqlCEVersionConverter(string file2convert)
{
connectionString = BuildConnectionString(file2convert);
}
Запускаем тест - тест проходит. Look nice. Но что-то не то. Дааа, ведь база данных может быть запаролена! Это значит, что нам нужен для конвертирования бд знать еще и пароль! Т.е. нам нужен еще конструктор, принимающий два аргумента (путь к файлу бд и пароль) и метод BuildConnectionString, тоже на два аргумента. Пишем соответствующие тесты (позволю себе пропустить их) и добавляем реализацию в класс SqlCEVersionConverter. Запускаем - тесты срабатывают! Но все равно мне не нравятся эти два метода BuildConnectionString, засоряют они своим присутствием ауру конвертера :) Во-первых, эти методы должны быть явно приватными. Но тогда их не потестишь. Во-вторых, конвертер должен конвертировать, а тут ему еще вписали в обязанности connection strings делать. Не порядок. Это явно противоречит Single Responsible Principle. Я сделаю небольшой рефакторинг - вынесу эти два метода в отдельный класс SqlCEConnectionStringBuilder. Но для этого сначала напишу соответствующие тесты. Ниже тест SqlCEConnectionStringBuilder.BuildConnectionString() на два аргумента:
[Fact]
public void BuildConnectionStringTest()
{
string sqlCEdbFile = @"C:\sqlCE35.sdf";
string password = "somepassword";
var builder = new SqlCEConnectionStringBuilder();
string connectionString = builder.BuildConnectionString(sqlCEdbFile, password);
Assert.Equal(@"Data Source=C:\sqlCE35.sdf;Mode=Exclusive;Password=somepassword", connectionString);
}
Просто копируем тела методов из SqlCEVersionConverter в SqlCEConnectionStringBuilder, запускаем тесты - срабатывают. Теперь изменяем конструкторы SqlCEVersionConverter, таким образом, чтобы использовался класс SqlCEConnectionStringBuilder:
public SqlCEVersionConverter(string file2convert, string password)
{
SqlCEConnectionStringBuilder builder = new SqlCEConnectionStringBuilder();
connectionString = builder.BuildConnectionString(file2convert, password);
}
И после этого удаляем из SqlCEVersionConverter методы BuildConnectionString(). Компилируем - все в порядке. Запускаем еще раз для уверенности тесты - все зеленое :)
Теперь осталось сделать форму и нацепить обработку событий. У меня форма получилась такой:
На форме есть чекбокс - Make backup file before convert. Из-за того, что в sql ce 4 используется SHA-2, sql ce 3.5 или более ранние версии не смогут работать с файлами данных sql ce 4. Поэтому было бы хорошо делать бэкап. А для этого нам нужен SimpleBackuper. Но сначала - тесты! :)
public class SimpleBackuperTests
{
[Fact]
public void BackupBeforConvertTest()
{
string file2backup = @"C:\sqlCE35.sdf";
var backuper = new SimpleBackuper();
backuper.MakeBackup(file2backup);
string backupFilename = @"C:\sqlCE35_backup.sdf";
Assert.True(File.Exists(backupFilename));
}
}
Сильно заморачиваться над методом создания бэкапа я не буду - использую простое переименование и копирование.
public class SimpleBackuper
{
public void MakeBackup(string file2backup)
{
var backupFileName = file2backup.Insert(file2backup.LastIndexOf('.'), "_backup");
File.Copy(file2backup, backupFileName, true);
return;
}
}
Вот теперь осталось совсем немного - написать обработку клика по кнопке Convert. Думаю, это описывать не надо :)
Заметьте, до этого момента мы еще ни разу не запустили программку (F5) - только компилировали (F6)! Время запустить и законвертировать наконец-таки какую-нибудь sql ce 3.5 бд в 4.0! И вот он, сюрприз! База из 3040 Кб - файла превратилась в 676 Кб-файл! Вот это отличная новость четвертого компакта!
Итак, подведем итоги. Мы разработали приложение в стиле TDD. Получили чистый код, который работает :) Как бонус, у нас получилось отличное отделение логики решаемой задачи от графического пользовательского интерфейса. И мы можем совершенно без страха изменить что-либо или добавить новый функционал в программу.
SqlCE 3.5 to 4.0 Converter
Подписаться на:
Комментарии к сообщению (Atom)
Ярлыки
.net
(17)
.net framework
(4)
256
(1)
армагедон
(1)
Библиотека
(12)
видео
(1)
вконтакте
(1)
декомпилятор
(1)
задачки
(5)
итоги
(1)
кодировка
(1)
космос
(1)
маркет
(1)
монетизация
(2)
мысли в слух
(10)
обфускация
(1)
Оптимизация сайта
(1)
отдых
(3)
Ошибка 720
(1)
переводы
(5)
подкасты для разработчика
(3)
прибыль
(1)
приложение
(2)
Разное
(28)
разработка ПО
(31)
рефакторинг
(5)
скачивания
(1)
ссылки
(2)
статистика
(1)
юмор
(31)
Access
(1)
admin2012.ru
(1)
admob
(1)
AMD
(1)
android
(6)
android conventions
(1)
android studio
(1)
angular.js
(1)
ant
(1)
antipattern
(1)
atdd
(2)
autocomplete
(1)
backbone.js
(1)
background repeat
(1)
batch file
(1)
batman.js
(1)
bdd
(3)
bootstrap
(1)
bug
(1)
build
(1)
C#
(31)
clojurescript
(1)
codeigniter
(1)
coding style
(1)
coffeescript
(3)
components
(1)
css
(1)
Custom splash screen
(1)
DDD
(1)
DI
(1)
eclipse
(1)
facebook
(1)
gradle
(1)
hot keys
(1)
html
(4)
ide
(1)
IE
(4)
IE8
(2)
IoC
(6)
ion auth
(1)
jasmine
(1)
java
(3)
javas
(1)
javascript
(9)
jquery
(4)
jquery ui
(1)
justify
(1)
knockout.js
(2)
linq
(3)
localDB
(1)
massive
(1)
micro orm
(1)
mocha
(1)
mock
(1)
mono
(1)
monodroid
(1)
moq
(2)
mpress
(1)
ms sql ce
(8)
msswit2013
(2)
mvc framework
(1)
mysql
(2)
NetBeans
(1)
nodejs
(1)
nosql
(1)
npm
(1)
object db
(1)
opera apps
(1)
ORM
(2)
phonegap
(1)
php
(12)
phpunit
(3)
play market
(2)
qunit
(1)
RegExpr
(2)
require.js
(1)
samsung apps
(2)
screenshoot
(1)
sdk
(1)
Shortcut
(1)
Silverlight
(4)
singleton
(1)
slide me
(1)
soap
(2)
social network
(1)
spellcheck
(1)
SpicIE
(1)
sql
(3)
sqlite
(4)
style
(1)
SublimeText 2
(5)
Super Mario
(1)
svn
(1)
tdd
(14)
tddigest
(5)
testing
(7)
text align
(1)
Tools
(18)
torrents.ru
(1)
tortoisesvn
(1)
twitter
(1)
uml
(1)
unit testing
(5)
unity
(3)
usability
(2)
virus
(1)
visual studio
(7)
web services
(2)
Windows 7
(1)
xunit
(3)
ZenCoding
(2)
Копирайты
Авторские права на публикуемые материалы (кроме тех материалов, где явно указан источник) принадлежат автору блога (мне) и могут быть использованы где-либо еще только с моего согласия.
Блог о жизни вне кода
Постоянные читатели
Популярно
-
Понравился анекдот о колбасе и яйцах :) Жена посылает мужа-программиста в магазин: - Дорогой, купи, пожалуйста, палку колбасы, и если б...
-
Продолжаю серию постов о своём первом андроид-приложении. Сегодня мысли о публикации приложения в разных маркетах.
-
Бета-версия одиннадцатой cтудии вызвала много охов и ахов. Чтобы там ни говорили, работать в ней приятно, хоть по началу немного необычно. ...
-
Jquery.Inputmask - крутой (да-да, именно) плагин, добавляющий гибкости в работу с обычным текстовым полем для ввода. Плагин является ус...
-
Перевод поста "Top 10 Things That Annoy Programmers" Кевина Панга. Оригинал тут
-
Фридман А.Л. - Основы объектно-ориентированной разработки программных систем. ( скачать ) Книга написана как учебное пособие для студентов ...
-
Steve Freeman, Nat Pryce. Growing Object-Oriented Software, Guided by Tests ( скачать ) Test-Driven Development (TDD) is now an established...
-
Для некоторых методов класса Microsoft Code Analysis даёт такой совет: CA1822 : Microsoft.Performance : The 'this' parameter (or ...
-
Разделяй и влавствуй - подход на все времена. Концепция модульного программирования не нова, и хорошо себя зарекомендовала. В мире разрабо...
0 коммент.:
Отправить комментарий