Object Explorer в MS SQL Server, как он должен быть

Давно собирался написать эту статью, о том каким должен быть Object Explorer в SQL Server.

В движок системы добавляются все новые и новые фишки, улучшается поддержка администрирования, скорость работы и так далее. Даже появляются сниппеты кода, а так же автодополнение в базовой версии, казалось бы, чего волноваться? Однако при постоянной работе с SQL Server, и когда хоткеи ReSharper’a уже хочется привнести в каждую программу, замечаешь насколько неудобная работа с объектами базы.

Все хорошо и красиво, когда в базе находится наверно не более 20 таблиц, которые можно объять одним взглядом, однако если таблиц от 50 и больше, а так же требуется работать с несколькими окружениями – работа превращается в ад. Очень легко выполнить не тот код, работая не с тем соединением. Да и просто поиск таблиц вызывает затруднения, так как обычно помнишь примерное название, а не дословное. Впрочем подобная проблема касается любых объектов в SQL Server.

Например глядя на такую картину, что вы можете сказать?

01

Что это за база? Какой это сервер? Сколько тут еще таблиц?

Подробнее

SQL Tips & Tricks

Сегодня в программе несколько интересных наблюдений и заметок по поводу SQL Server. Советы и заметки ниже применимы к любым актуальным версиям SQL Server (таковыми считаются все версии от 2005 и новее). Итак:

  • Получение изменившихся данных без триггеров
  • Select vs Set для установления переменных
  • Забытое дополнение для TOP

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

Получение изменений без триггеров

Действительно большинство пользователей MS SQL Server думают, что триггеры это единственное место где можно использовать виртуальные таблицы Inserted и Deleted, с помощью которых можно получить данные об измененных данных в результате выполнения запросов с Insert, Update или Delete. Но, как вы уже наверно догадались, это не так.

Любые изменения в данных, которые проводятся с помощью DML операций могут быть «захвачены» в специальные виртуальные таблицы упомянутые выше. Для этого в запросе надо использовать служебное слово output и перечислять поля которые вы хотите записать в нужную таблицу.

Подробнее

Безопасные пароли с SqlCredential

Наткнулся на описание новой фичи, которая входит в .Net 4.5, которая должна упростить работу с безопасным хранением паролей к базе данных. Раньше это был, на мой взгляд, какой-то не очень удобный способ с файлами конфигурации, какими-то специальными преобразованиями и чем-то еще. Сейчас же появилась возможность создания безопасных данных о подключении к базе данных, которые не утекут при снятии дампа памяти целенаправленно или случайно в результате аварийной остановки программы, да мало ли какие случаи бывают. Честно сказать, в моей практике доступ к БД в основном осуществлялся с помощью Active Directory, что существенно упрощало работу. Однако такое тоже было не всегда и меня внутренне грыз червячок сомнений о несколько легкомысленном отношении к строкам соединений к БД. Сейчас появился достаточно простой и легкий способ защитить данные о соединении с базой с помощью класса SqlCredential. Теперь стало возможно задать логин\пароль с помощью свойства Credential у класса SqlConnection.

Лучше всего сразу это показать на примере, мне кажется, это будет лучше тысячи слов =)

Подробнее

EF5 шаблонный AddOrUpdate

Сложность 400

Продолжаю разбирать и ковырять Entity Framework на предмет его использования в реальной жизни, какие плюсы есть, чего стоит опасаться, какие сценарии использования наиболее продуктивны, и как его можно использовать в существующих сценариях.

Одним из таких сценариев, который дает о себе знать сразу, как только вы начинаете использовать EntityFramework в более-менее настоящем проекте, а не в синтетических тестах и приложениях – это вопрос добавления и обновления данных.

Не каждый раз и не во всякой ситуации можно отталкиваться и работать с объектами связанными с контекстом базы. Особенно если это какое-либо веб-приложение, хотя и в корпоративном десктопном ПО хватает примеров. Чаще всего требуется по каким-либо косвенным признакам определять новый объект или нет, или же производить поиск в базе по первичным ключам, и далее уже решать, сохранять или добавлять элемент.

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

Подробнее

EF5 Описание команд миграции

Основное управление скриптами миграциями для Entity Framework осуществляется из консоли менеджера пакетов, которая суть есть PowerShell, и во многих уроках и разборах упоминаются лишь базовые команды и опции, и не особенно фигурируют другие возможности. Решено было озаботиться составлением такого списка.

Основных команд, как и ожидалось всего 4:

  • Enable-Migrations – включает возможность миграции в EF
  • Add-Migration – добавляет/генерирует новую миграцию
  • Update-Database – обновление базы данных
  • Get-Migrations – показывает какие обновления были применены к БД

EF5 RF CF — Force Recovery Mode

Сложность 200

Или как заставить базу думать, что у вас новая модель.

В одном из прошлых постов я рассказывал о механизме миграции и о проблеме, которая возникает, если сначала создать скрипт миграции, а потом поменять модель. Т.е. не меняя модели, имея базу данных актуальном состоянии, создаем файл миграции командой

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

Как мы выяснили еще в прошлый раз, все дело в поле Model, в котором теперь содержится не хэш модели, но вся модель в заархивированном виде, для того, чтобы можно было проводить анализ изменений, а не просто говорить, были изменения или нет.

Подробнее

EF5 RC CF — Механизм миграции

Entity Framework 5 Release Candidate Code First: Механизм миграции

Сложность 200.

Видимо настал тот момент, когда можно обратиться к Entity Framework, тем более что поступающая информация все сильнее и сильнее радует меня и EF обретает любопытные черты и свойства. Пятая версия фреймворка, в моих глазах уже может претендовать на то, чтобы появиться в боевой среде.

Более всего меня увлекает на данный момент подход CodeFirst, с возможностью миграций, т.е. поддержкой версионности базы. Очевидно на многих, достаточно простых сценариях, миграции отрабатывают хорошо, генерируя скрипты миграции вверх и вниз. Что весьма и весьма полезно. Однако нашлась ложка дегтя в этой бочке меда, либо я чего-то специфического не знаю, о чем все молчат =). Но обо всем по порядку.

Подготовка

Нам понадобится база данных MS SQL. В моем случае это SQL Server 2012, вы можете поставить себе Express версию, хотя скорее всего она уже есть у вас. Далее понадобится .net framework не ниже 4 версии. Конечно же Visual Studio и менеджер пакетов NuGet.

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

Подробнее

GUID в роли быстрого первичного ключа для разных БД

Эта статья раскрывает подходы по использованию GUID в роли первичного ключа или кластерного индекса при этом описываются способы обхода основных неудобств связанных с GUID, на основании COMB модели для последовательных значений GUID разработанных в статье Джимми Нильсона. Большинство реализаций являются специфичными для MS SQL Server, в то время как основная идея похоже используется во многих библиотеках и фреймворках(включая NHibernate). В статье предпринимается попытка использовать общий гибкий подход для возможности использования COMB в других популярных базах данных: Oracle, PostgreSQL, MySQL. Так же мы рассмотрим некоторые особенности .net в свете наших задач.

Проблематика GUID

Исторически сложилось так, что наиболее общим подходом в проектировке БД для идентификации конкретной строки использовалась целочисленная последовательность. Как правило, такая последовательность генерируется на стороне сервера в момент вставки новой строки. Такой простой и ясный подход подходит для многих приложений.

Тем не менее, есть некоторое количество ситуаций, когда такой подход не будет хорош. При широком применении ORM фреймворков большинство пользователей стараются избежать лишних сложностей на стороне БД, а формирование ключа на стороне БД к таким сложностям можно отнести. Репликация баз данных так же становится затруднительной, если полагаться только на единственный внутрибазовый сервис для генерации ключей. Требуется внешний источник для минимизации зависимостей от того, как генерируются ключи.

Одной из альтернатив становится использование GUID в роли первичного ключа. GUID — это 128-битное значение, которое поддерживает разумно-гарантированную уникальность независимо от времени и пространства. Стандарт для создания GUID описан в документе RFC 4122, но большинство современных алгоритмов по созданию GUID используют либо очень большое случайное число, либо формируют значение исходя из некоторой случайной информации комбинированной с чем-то локальным (ранее такое формирование было у MS, они создавали GUID на основе MAC адреса, но в последствии это было не безопасно и так же нарушало privacy).

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

Так в чем же проблема?

Подробнее

Procedure Façade

Сложность 300

В прошлый раз, когда речь шла об инфраструктурном слое, я упомянул, что в текущем своем виде он не подходит для удобного использования процедур, если таковые имеются. Однако многие проекты до сих пор могут вынужденно использовать процедуры как наследие предыдущих версий. Впрочем, с некоторым удивлением можно обнаружить и новые проекты, которые активно используют процедуры вплоть до CRUD реализаций.

В этом посте я хочу рассказать, как можно сделать использование процедур как можно более простым для вашего кода и лишить себя многой тупой работы и кода. Приведенный ниже пример будет основываться на Linq2Sql контексте, но общая идея, я уверен, подойдет и для EF. Для тех, кто не читал цикл о фасаде доступа к данным, рекомендую сначала прочитать его, так все примеры ниже будут основаны на описанном примере и внимание будет уделено только работе с процедурами.

Идея

Общая идея совсем не нова и основывается на принципе Convention over Configuration. Т.е. все работает «как бы магическим образом», основываясь только на специальных правилах именования. Когда-то давно это не казалось  хорошей идеей, однако такая договоренность значительно упрощает жизнь и сейчас данный принцип используется во многих проектах и фреймворках. Взять хотя бы тот же ASP.NET MVC, который полностью построен на специальных названиях, папках и тому подобное, никто ведь не жалуется, даже скорее наоборот. Конечно, работа проектов на соглашениях кажется «магией», пока не начинаешь работать с ними и глубоко разбираться в механизмах лежащих глубоко внутри. Впрочем, для правильного и эффективного использования в любом случае придется овладеть «магией», которая превратится в простую ловкость рук.

Подробнее

Фасад доступа к данным — Оптимизация, Заключение

Построение запросов

Уже традиционно покажу сразу UML схему, чтобы вы смогли ощутить какие классы будут рассмотрены и как они зависят друг от друга.

Хорошо уметь загружать связанные данные, хорошо уметь восстанавливать только нужные данные, но было бы еще замечательно уметь получать только нужные данные от базы данных, чтобы не выкачивать многие тысячи строк, которые нам может и не нужны вовсе. Для этих целей и существует в нашей схеме построители (или оптимизаторы) запросов.

Linq2Sql позволяет гибко работать с запросами в стиле fluent interface переводя их в sql запросы. Было бы упущением не воспользоваться этой возможностью в полной мере. Особенно учитывая то, что мы уже работаем с логическими таблицами L2S, которые реализуют интерфейс IQueryable. Да, когда мы в адаптере чтения обращаемся к контексту с методом GetTable<TData>(), мы получаем объект, который можно донастраивать с помощью методов Where(), разбирая пользовательские спецификации. Собственно в этом и состоит идея.

Следуя только что сказанному, интерфейс для построения запросов может выглядеть следующим образом:

Модифицировали запрос, если надо, и отдали его обратно. Отлично, теперь рассмотрим как это может быть реализовано.

Подробнее