25 августа 2017 г.

MSSQL DATETIME2, DATETIME truncate минуты, секунд.

В какой то момент может понадобится  возможность в SQL запросе по полю типа DATETIME или DATETIME2 производить сравнение дат с какой то конкретной датой, отбросив при этом минуты, секунды, миллисекунды. Для дат, которые лежат в настоящие годы, это можно сделать без каких либо проблем через DATEADD и DATEDIFF. Пример использования с обрезанием до минут:

SELECT DATEADD(MINUTE, DATEDIFF(MINUTE, 0, '2017-08-25 00:00'), 0)

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

Все было бы хорошо, но есть ложка дёгтя в бочке с медом. DATEDIFF возвращает количество прошедших минут, секунд, миллисекунд с 1900-01-01 00:00:00 при этом возвращаемое значение INT. Это значит:
  • Даты до 1900 года будут иметь отрицательное значение
  • Мы имеем ограничение на возвращаемое значение, равное диапазону значений INT, а это ровняется от -2,147,483,648 до +2,147,483,647.
  • Чем меньшую единицу измерения времени мы хотим обрезать, тем ближе к 1900 году должна быть дата в таблице.
При этом, максимальный год для DATETIME и DATETIME2 это 9999. И если в таблице будет присутствовать значение, которая будет приводить к переполнению INT при вычисление DATEDIFF - вы будете получать ошибку на ваш SQL запрос:
The datediff function resulted in an overflow. The number of dateparts separating two date/time instances is too large. Try to use datediff with a less precise datepart.

15 августа 2017 г.

Решение проблемы при установке ccollab клиента.

Столкнулся с проблемой при обновлении клиента Code Review - Collaborator от SmartBear с 6.x на 11.x. Для установки я удалил старую версию и решил поставить новую, но в ответ получил ошибку:


Формат текста ошибки следующий:
The installation/removal of a previous program was not completed. You will need to restart your computer to complete that installation.\n\nAfter restarting your computer, run Setup again to complete the installation of {0}.
Для её решения я используя Process Explorer открыл текущую директорию у для установщика, она была во временной папке по пути C:\Users\SAP\AppData\Local\Temp\[Random], в папке содержался файла MessagesDefault в котором было само сообщение с ключем PreviousInstallNotCompleted. Декомпилировав было выяснено, что в файле i4jruntime.jar, лежащем в каталоге, содержится часть логики установщика. После непродолжительного анализа была найдена проверка и выдача ошибки, а логика такая:
  • Читаем из HKEY_CURRENT_USER и HKEY_LOCAL_MACHINE значение RebootCheckFile по адресу SOFTWARE\ej-technologies\install4j\.
  • Если файл по пути RebootCheckFile существует то падаем с ошибкой.
Почему у меня не удалился файл я не знаю, но действительно, по пути C:\Users\SAP\AppData\Local\Temp\ существовал пустой файл, который стопарил все.



Удаляем RebootCheckFile и все! Установка должна пройти успешно.

14 августа 2017 г.

Учим Ecm7.Migrator работать с MSSQL типом DATETIME2

Сегодня хотелось бы рассказать зачем мы начали использовать ECM7.Migrator и как его научить понимать DbType.DateTime2 на версии ECM7 2.8.0.0.

Зачем использовать ECM7?


Всю информацию можно узнать на сайте проекта ECM7.Migrator ссылка на NuGet. Тут я опишу почему мы его стали использовать на работе. В решениях используем EntityFramework с Code First подход при работе с базой данных. Для этого EntityFramework умеет создавать, на основе объектной модели, сущности в базе данных. Данные об этих сущностях хранятся в миграциях, а их применением и версионностью занимается DbMigrator. Все было бы хорошо, но есть одно ограничение - все миграции должны находиться в проекте с DbContext. И в ситуации, если решение состоит из плагинов, каждому из которых требуется своя структура в базе, это ограничение требует, что бы все миграции до подключения плагина уже были применены к базе. Но в этом случае теряется смысл в выделении модулей и подключении только нужных.

Для решения мы использовали ECM7.Migrator, на который пришлось переписать создание базы данных решения, а модульные миграции без проблем перенесли в другие сборки.

Работа с DateTime2.


Решения из коробки у версии ECM7 2.8.0.0, для работы с типом DateTime2, найдено не было, но это лечится простым добавлением типа в карту типов SqlServerTransformationProvider.


using System.Data;
using System.Data.SqlClient;
 
namespace ECM7.Migrator.Providers.SqlServer
{
    /// <summary>
    /// Extended <see cref="SqlServerTransformationProvider"/> MSSQL provider.
    /// </summary>
    internal class ExtendedSqlServerTransformationProvider : SqlServerTransformationProvider
    {
        /// <summary>
        /// <see cref="ExtendedSqlServerTransformationProvider"/> constructor.
        /// </summary>
        public ExtendedSqlServerTransformationProvider(SqlConnection connection, int commandTimeout)
            : base(connection, commandTimeout)
        {
            typeMap.Put(DbType.DateTime2, "DATETIME2");
        }
    }
}
 

13 августа 2017 г.

WPF/WinForms Хостинг (встраивание) окна чужого win32 приложения.

Ссылка на пример из статьи:
https://bitbucket.org/sergey_vaulin/wpf-application-host


Хочу поделиться с вами способом, как можно окно внешнего приложение "встроить" в свою программу. Ситуация из жизни: разрабатывая CRM систему для заказчика может появиться потребность, в одном из сценариев обслуживания, дать пользователю возможность произвести какие то манипуляции во внешней системе. Если эта система является Web сайтом, то задача решается добавлением WebBrowser на форму. Но представьте, что это какое то приложение, и что тогда делать?
Для этого можно провернуть трюк используя WinAPI, в результате которого окно внешнего приложения окажется "внутри" нашего (как будто экран виртуальной машиной), но у заказчика будет складываться иллюзия того, что мы его запустили внутри нашего приложения. И это похоже на магию.

В примере, ссылка на который имеется в начале статьи, я добавил TabControl, у которого на вкладках размещены три стандартных Windows приложения:
  • Notepad - блокнот.
  • Write - простой редактор документов.
  • Regedit - редактор реестра.
Если запустить пример и переключать закладки, то можно увидеть приведённый на скриншотах ниже, результат работы:

Блокнот: