15.01.2022

Тренажёр для работы с Git

Наткнулся на отличный тренажёр для работы с git-ом (https://learngitbranching.js.org/), который поможет новичкам освоить работу с ветками, а также обучит другим полезным трюкам. Рекомендую.

27.09.2021

Azure: построение кросс-запросов для различных БД в MS Azure SQL Server

 MS Azure SQL Server с точки зрения взаимодействия с ним крайне похож на классический MS SQL Server и во многих аспектах повторяет функциональность. Однако быстрое и удобное создание linked server пока не доступно в Azure версии. В качестве решение можно воспользоваться способом с подключением внешнего источника данных:

-- Производим очистку данных
DROP EXTERNAL TABLE tblSource
DROP EXTERNAL DATA SOURCE RemoteSource
DROP DATABASE SCOPED CREDENTIAL sourceCredential
DROP MASTER KEY

-- Настраиваем соединение
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'your_password';

CREATE DATABASE SCOPED CREDENTIAL sourceCredential
WITH IDENTITY = 'your_login',
SECRET = 'your_password';

CREATE EXTERNAL DATA SOURCE RemoteSource
WITH
(
    TYPE=RDBMS,
    LOCATION='your_server.database.windows.net',
    DATABASE_NAME='your_db_name',
    CREDENTIAL= sourceCredential
);

CREATE EXTERNAL TABLE dbo.tblSource(
    [Id] [int] NOT NULL,
    [Name] [nvarchar](2000) NOT NULL
)
WITH
(
    DATA_SOURCE = RemoteSource
);

-- Производим выборку
SELECT * 
FROM dbo.tblSource

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

21.09.2021

.NET: compiling single file executables in .NET 5

 .NET 5 is not a very new technology, very soon MS will perform release version of .NET 6. Hovewer 5th version is still in use and not all problems were solved in it. One of such problems is compiling single file executables. If you try to do it just by selecting checkbox in publish settings window, just like you did for .Net core 3.1 and ealrlier, it will not work. Visual Studio will still compile multifile build. 

Here is a workaround for it. You will need to manually add properties (PublishSingleFile, SelfContained, IncludeAllContentForSelfExtract and RuntimeIdentifier) in your project file. Thus you csproj will look like this:

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <OutputType>WinExe</OutputType>
        <TargetFramework>net5.0-windows</TargetFramework>
        <PublishSingleFile>true</PublishSingleFile>
        <SelfContained>true</SelfContained>
        <IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>
        <RuntimeIdentifier>win-x64</RuntimeIdentifier>
    </PropertyGroup>
</Project>

Of course your parameters (like runtime or generated file type) may be different according to your task.

20.09.2021

MS Office: снятие защиты с файла Word, Excel, PowerPoint

Как известно современные файлы из пакета MS Office (docx, xlsx и т.п.) являются переименованными zip архивами, содержимое которых легко можно просмотреть. Поэтому есть достаточно простой способ снятия защиты с документа/листа. Пример для Excel можно посмотреть в этом видео:


PS. Надеюсь в следующей ревизии это исправят.


20.04.2021

SQL: Функция для получения по подстрок из строки с разделителями

Возникла задача по разбиения строкового столбца, в котором есть разделители, например, точка с запятой на отдельные столбцы. Для этого из оригинальной строки нужно получать подстроки с учетом порядкового номера/индекса. Сделать это можно, написав sql-функцию следующего вида:

CREATE FUNCTION [dbo].[f_GetValueFromSeparatedStringByIndex]
(
    @InputString nvarchar(MAX),
    @Index int,
    @Separator nvarchar(1) = ';'
)
RETURNS nvarchar(255)
AS
BEGIN
    DECLARE @Result nvarchar(255) = NULL

    SELECT @Result = TRIM(Value)
    FROM (
        SELECT TRIM(value) as Value, ROW_NUMBER() OVER(ORDER BY (SELECT 1)) as OrderNumber
        FROM string_split(@InputString, @Separator)
    ) as t
    WHERE OrderNumber = @Index

    RETURN  @Result
END

31.03.2021

.Net библиотеки для работы с маркетинговыми системами

В конце прошлого кода на своей текущей работе в компании Wavemaker (Russia) запустил несколько opensource решений, базирующихся на наработках, сделанных в ходе работы над программным комплексом Data Feeds Platfrom. Часть функциональности задействует ряд библиотек из моего фреймворка Ak.Framework. Как раз недавно было выпущено обновление для одной из библиотек. 

Что было сделано:

Adverity.Api.Connector - библиотека для работы с API Adverity Datatap.

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

Github - https://github.com/wm-russia-software/Adverity.Api.Connector

Nuget - https://www.nuget.org/packages/Adverity.Api.Datatap.Connector


Segmento.Api.Connector - библиотека для работы с API Segmento.

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

Github - https://github.com/wm-russia-software/Segmento.Api.Connector

Nuget - https://www.nuget.org/packages/Segmento.Api.Connector

Делитесь и пользуйтесь.


25.03.2021

Azure: Проблема масштабирования SQL Database при включенном резервном копировании

Недавно наткнулся на интересный момент. В рамках MS Azure при попытке перемасштабировать базу с DTU-варианта на виртуальные ядра с включенным автоотключением падает неизвестная ошибка без какой-либо детализации. Экспериментальным образом удалось выяснить, что проблема заключалась в настроенном у БД резервном копировании. При его оключении масштабирование проходит успешно. 

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

24.02.2020

SQL: Получение списка запросов, ожидающих доступ к вычислительным ресурсам

Иногда запрос может выполняться очень долго, т.к. не может получить доступ к вычислительным ресурсам. Такое часто встречается при большом количестве одновременных обращений из разных источников. Получить список всех запросов, ожидающих доступ к ресурсам, в MS SQL Server можно следующим образом:
SELECT  wt.session_id, 
        ot.task_state, 
        wt.wait_type, 
        wt.wait_duration_ms, 
        wt.blocking_session_id, 
        wt.resource_description, 
        es.[host_name], 
        es.[program_name] 
FROM  sys.dm_os_waiting_tasks  wt  
INNER  JOIN sys.dm_os_tasks ot ON ot.task_address = wt.waiting_task_address 
INNER JOIN sys.dm_exec_sessions es ON es.session_id = wt.session_id 
WHERE es.is_user_process =  1 

SQL: Остановка длительных запросов

Если база данных является высоконагруженной и работает в конкурентном окружении, то достаточно часто возникает задача остановки длительных запросов, если они мешают выполнению других запросов. Приведу здесь наиболее популярные конструкции для поиска и удаления запросов.
  1. Получение списка всех активных сессий вместе с учетными записями, под которыми они запущены:
    SELECT conn.session_id, host_name, program_name,
        nt_domain, login_name, connect_time, last_request_end_time 
    FROM sys.dm_exec_sessions AS sess
    JOIN sys.dm_exec_connections AS conn
       ON sess.session_id = conn.session_id
    
  2. Получение списка всех запущенных запросов с индентификатором открытой сессии и временем запуска:
    SELECT  sqltext.TEXT,
            req.session_id,
            req.status,
            eq.start_time,
            req.command,
            req.cpu_time,
            req.total_elapsed_time
    FROM sys.dm_exec_requests req
    CROSS APPLY sys.dm_exec_sql_text(sql_handle) AS sqltext
    
  3. Получить информацию о том, какие активные соединения в настоящее время установлены с SQL Server, можно так:
    sp_who2 'active'
    
  4. Завершение пользовательского процесса по идентификатором сеанса:
    KILL 'your_session_id'
    

16.02.2020

Ошибка "Package is not found in the following primary source(s): 'https://api.nuget.org/v3/index.json"

Периодически приходится собирать nuget-пакеты и выкладывать их на nuget.org. После публикации попытался обновить библиотеку и получил ошибку "Package 'your package' is not found in the following primary source(s): 'https://api.nuget.org/v3/index.json". При этом в хранилище пакетов гарантирована была необходимая версия в состоянии Listed.
Причина проблемы оказалось в некорректном кэшировании списка доступных пакетов в Visual Studio. Для устранения проблемы нужно просто почистить кэш nuget. Для этого нужно выполнить следующий набор действий: Tools -> Nuget Package Manager -> нажать кнопку Clear All NuGet Cache(s).

11.10.2019

C#: Running a program in a single instance

Sometimes you need to run your program just in a single instance. For example it can happen when you use some resources which can not be shared (devices, databases or something else). In this case the following method of running your program can help:
class Program
{
     static void Main(string[] args)
     {
          bool existed;
          // obtaining application GIUD
          string guid = Marshal.GetTypeLibGuidForAssembly(Assembly.GetExecutingAssembly()).ToString();

          Mutex mutexObj = new Mutex(true, guid, out existed);

          if (existed)
          {
               Console.WriteLine("Application is already running");
          }
          else
          {
               Console.WriteLine("This is the first instance of this application.");
          }

          Console.ReadLine();
     }
}

04.09.2019

Python: Online IDE

Бывают ситуации, когда нет возможности установить на компьютер необходимую среду разработки (например, из-за ограничений политик безопасности компании) или нужно проверить идею. В этом случае могут помочь облачные IDE. Здесь приведен список наиболее популярных сервисов, поддерживающих Python, хотя некоторые из них могут использовать и другие языки:
  1. repl.it
  2. sourcelair.com - также поддерживает js.
  3. jupyter.org/try - один из самых популярных редакторов. Позволяет использовать не только Python, но и R, C++, Ruby и Scheme.

C#: Поиск элементов в списке строк без учета регистра

Небольшое, но полезное расширение для List<string>, позволяющее осуществлять поиск элементов в списке строк без учета регистра:
public static bool Contains(this string target, string value, StringComparison comparison)
{
    return target.IndexOf(value, comparison) >= 0;
}

23.07.2019

SQL: получение информации о всех таблицах

При проектировании больших баз данных я всегда стараюсь давать всем таблицам максимально понятные названия, а также, если это позволяет сделать БД, создавать описания к таблицам. Это очень удобно, когда таблиц становится очень много, а ты сам уже начинаешь забывать для чего та или иная таблица, а также при введении в курс дел нового разработчика. Однако прокликивать все таблиц, чтобы прочитать описание, очень не удобно. В рамках MS SQL Server может быть удобен следующий скрипт, который выводит список названий таблиц, их схему, дату создания и дату последнего изменения таблицы, а также количество записей и описание:
SELECT schema_name(tab.schema_id) as schema_name,
       tab.name as table_name, 
       tab.create_date as created,  
       tab.modify_date as last_modified, 
       p.rows as num_rows, 
       ep.value as comments 
FROM sys.tables tab
    INNER JOIN (SELECT DISTINCT 
                        p.object_id,
                        sum(p.rows) rows
                FROM sys.tables t
      INNER JOIN sys.partitions p on p.object_id = t.object_id 
                GROUP BY p.object_id, p.index_id) p
        on p.object_id = tab.object_id
    LEFT JOIN sys.extended_properties ep 
        on tab.object_id = ep.major_id
        and ep.name = 'MS_Description'
        and ep.minor_id = 0
        and ep.class_desc = 'OBJECT_OR_COLUMN'
ORDER BY schema_name, table_name
Иногда нужно просто получить список таблиц и количество записей в них, для этого можно воспользоваться более простым скриптом:
SELECT o.NAME, i.rowcnt 
FROM sysindexes AS i
 INNER JOIN sysobjects AS o ON i.id = o.id 
WHERE i.indid < 2  AND OBJECTPROPERTY(o.id, 'IsMSShipped') = 0
ORDER BY o.NAME

09.06.2019

SQL: генерация списка дат и недель

Иногда для решения задачи бывает удобно получить список недель или последовательность дат для дальнейшего объединения с другими данными из БД. Получить список дат в указанном диапазоне можно таким образом (применительно к T-SQL):
DECLARE @StartDate date = '20190101'
DECLARE @EndDate date = '20191231'

;WITH calendarDates as
( 
   SELECT dt = @StartDate

   UNION ALL

   SELECT DATEADD(DAY, 1, dt)
   FROM calendarDates
   WHERE DATEADD(DAY, 1, dt) <= @EndDate
)

SELECT *
FROM calendarDates
ORDER BY dt
OPTION (MAXRECURSION 0)

Если нужно получить список всех дат начала недели, то пригодится такой трюк:
DECLARE @StartDate date = '20190101'
DECLARE @EndDate date = '20191231'
DECLARE @WeekStartDate date =  DATEADD(DAY, 2 - DATEPART(ISO_WEEK, @StartDate), CAST(@StartDate AS DATE))
DECLARE @WeekEndDate date = DATEADD(DAY, 8 - DATEPART(ISO_WEEK, GETDATE()), CAST(GETDATE() AS DATE))

;WITH calendarDates as
( 
   SELECT dt = @WeekStartDate

   UNION ALL

   SELECT DATEADD(DAY, 7, dt)
   FROM calendarDates
   WHERE DATEADD(DAY, 7, dt) <= @EndDate
)

SELECT *
FROM calendarDates
ORDER BY dt
OPTION (MAXRECURSION 0)

03.03.2019

SQL: быстрый подсчет количества записей в таблицах

Периодически встречается ситуация, когда нужно посчитать количество записей в очень больших таблицах, содержащих миллионы и более записей. При этом стандартная функция COUNT(*) для них отрабатывает крайне долго, даже при использовании грязного чтения (WITH (NOLOCK)). В рамках T-SQL есть несколько трюков, которые не всегда точны, но позволяют быстро оценить количество записей, что может быть полезно при последующей оптимизации запросов.

Способ №1:
SELECT SUM(row_count)
FROM sys.dm_db_partition_stats
WHERE object_id=OBJECT_ID('tblYourTableName')   
 AND (index_id=0 or index_id=1)

Способ №2:
SELECT CONVERT(bigint, rows)
FROM sysindexes
WHERE id = OBJECT_ID('tblYourTableName')
 AND indid < 2

Способ №3:
SELECT CAST(p.rows AS float)
FROM sys.tables AS tbl
 INNER JOIN sys.indexes AS idx ON idx.object_id = tbl.object_id and idx.index_id < 2
 INNER JOIN sys.partitions AS p ON p.object_id=CAST(tbl.object_id AS int) 
            AND p.index_id=idx.index_id
WHERE ((tbl.name=N'tblYourTableName'
 AND SCHEMA_NAME(tbl.schema_id)='dbo'))

16.02.2019

Azure: ошибка 425 при подключении к FTP

На Azure была создана свежая виртуальная машина, на которой был развернут FTP-сервер Filezilla. В брендмауэре как винды, так и виртуальной машины был открыт входящий порт 21 (по умолчанию для FTP). Соединение с сервером выполнялось, но после хендшейка выдавалась ошибка 425, после чего соединение падало.
Ларчик открывался просто: FTP- сервер сообщал клиенту, что нужно использовать порты для пассивного режима, по умолчанию для Filezilla  это 6091-6092. Поэтому, чтобы все заработало нужно открыть их во всех фаерволах.

Azure: solving KMS license activation problem on virtual machines

For about a month I had a lot of work with Microsoft Azure. This cloud is best I worked with, however even it has some bugs. I fpind that sometimes newly created Windows Server or Window 10 virtual machines can not be automatically activated. After several iterations of commucation with MS tech support we found the solution of the problem. Follow the steps:
  1. First of all you should check the availability of Azure KMS server with the following cmd command:
    nslookup -type=srv _vlmcs._tcp
    
  2. Set a proper key for your Windows version:
    slmgr.vbs -ipk 
    
    The list of keys can be found here. For example for Win2k12 it will be
    slmgr.vbs -ipk W3GGN-FT8W3-Y4M27-J84CP-Q3VJ9
    
  3. Set a correct KMS server:
    slmgr /skms kms.core.windows.net:1688
    or
    slmgr.vbs -skms http://kms.core.windows.net:1688
    
  4. And finally perform activation:
    slmgr.vbs /ato
Some steps can be overkill with your particular case, but sometimes you should repeat a command to get it working. Hope it helps.

Confluence: unknown server error при создании пространства

На днях разворачивал Confluence 6.14, после добавления пары новых плагинов и перезагрузки перестали создаваться новые пространства. При этом выдавалось сообщение "An unknown server error has occurred". Проблема, как и можно было предположить, крылась в ошибках шаблонов пространств. Помогло удаление соответствующих таблиц:

DROP TABLE AO_54C900_SPACE_BLUEPRINT_AO
DROP TABLE AO_54C900_C_TEMPLATE_REF
DROP TABLE AO_54C900_CONTENT_BLUEPRINT_AO

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