Показаны сообщения с ярлыком Tricks. Показать все сообщения
Показаны сообщения с ярлыком Tricks. Показать все сообщения

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

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();
     }
}

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'))

30.01.2019

SQL: Использование функции RAND внутри другой функции

Не так давно писал на T-SQL генератор данных, включающий в себя функцию со случайным значением шума. Наткнулся на то, что функция RAND() не может быть использована в рамках UDF (user defined function), выдавая при этом сообщение "Invalid use of a side-effecting operator ‘rand’ within a function". Удалось найти достаточно интересны способ обхода данного ограничения. 
Сначала необходимо создать представление, которое при каждом вызове будет генерировать новое рандомное значение:

CREATE VIEW v_RandomizeView
AS
SELECT RAND() AS Result

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

CREATE FUNCTION f_Randomize()
RETURNS float
AS
BEGIN
   RETURN 2 * (SELECT TOP 1 Result FROM v_RandomizeView) - 1
END
GO

12.09.2018

WPF: несколько полезных трюков

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

1. Биндинг команд к событиям
Если разработчик хочет придерживаться MVVM модели, то для обработки событий он не сможет использовать стандартный обработчик команды в codebehind его xaml-формы. Для того, чтобы привязать событие и команду из ViewModel, он может использовать трюк, который предлагает JonghoL. В этом случае вам нужно просто написать следующий код:


Здесь добавляется пространство имен eb, в котором реализован класс EventBinding, который, в свою очередь может получать на вход название команды из ViewModel и возвращать в неё параметр.


2. Конвертер строки в BitmapImage
Когда программист добавляет на форму изображение и делает связку источника изображения с путем к какому-либо файлу, то доступ к данному файлу блокируется. Это не всегда удобно, например, если вы разрабатываете редактор изображений, то вам может понадобиться сохранение и удаление временных файлов, а они будут залочены элементом управления. В такой ситуации можно написать конвертер, преобразующий путь к изображению в BitmapImage, и использовать его при биндинге как обычный конвертер. Конвертер будет выглядеть так:

public sealed class StringToBitmapImageConverter : ValueConverterBase
{
    public override object Convert(object value, Type targetType, 
        object parameter, CultureInfo culture)
    {
        object result = null;

        if (value is string uri)
        {
            BitmapImage image = new BitmapImage();
            image.BeginInit();
            image.CacheOption = BitmapCacheOption.OnLoad;
            image.UriSource = new Uri(uri);
            image.EndInit();
            result = image;
        }

        return result;
    }
    
    public override object ConvertBack(object value, Type targetType, 
        object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}


3. Создание пунктирной рамки 
В WPF нет стандартной кисти для реализации пунктирной линии границы. Для реализации такого стиля существуют разные подходы, в т.ч. с использованием codebehind. Приведу тот, который нравится мне, при необходимости его можно модифицировать под конкретную задачу:
<LinearGradientBrush x:Key="CropRectangleAreaBorderBrush" 
                     MappingMode="Absolute"
                     SpreadMethod="Repeat"
                     StartPoint="0,0"
                     EndPoint="30,30">
    <GradientStop Offset="0" Color="#40009299" />
    <GradientStop Offset="0.5" Color="#40169E4C" />
    <GradientStop Offset="0.501" Color="Transparent" />
</LinearGradientBrush>


PS. Функциональность, представленная в пунктах 1 и 2, а также множество других полезных классов и методов, доступна в разрабатываемом мной фреймворке на github, а такжк в nuget-пакетах: Ak.Framework.Wpf и Ak.Framework.Core.

10.07.2018

Javascript: как быстро отформатировать минимизированный код

Когда сайт выкладывается на продуктив, хорошим стилем является минимизация css и js-файлов с целью уменьшения объема данных, загружаемого на клиента. Однако периодически возникает необходимость решения обратной задачи для приведения минимизированного кода в красиво отформатированное читабельное представление. Например, такое может понадобиться для анализа кода чужой системы, с которой вы планируете интегрироваться, а документации у вас нет. Для быстрого преобразования скриптов в читабельный вид (особенно в полевых условиях) очень удобным оказался сайт - http://jsbeautifier.org. Рекомендую!  

05.07.2018

Как преобразовать 3d видео для раздельной стереопары в 2d

Некоторые редкие фильмы, выходящие, например, только на dvd, можно найти только в 3d формате. Если найденные фильм сделан как раздельная стереопара (вертикальная или горизонтальная), то его можно легко и просто сконвертировать в обычный 2d. Для этого рекомендую воспользоваться программой Pavtube Video Converter, хотя аналогичные операции можно провести и с помощью других конвертеров. Дальше по шагам:
  1. Загрузите видео в программу.
  2. Откройте редактор (см. рисунок), в редакторе укажите размер обрезки, либо вручную задав область, либо указав числовые значения. После этого установите способ вывода - растянуть.
  3. Выберите необходимый выходной формат и путь экспорта.
  4. Запустите конвертацию.
  5. После длительного ожидания видео будет сконвертировано и можно наслаждаться просмотром.


PS Просматривать стереопарные видео можно и с помощью проигрывателей, но передо мной стояла задача конвертации в 2d для загрузки в домашнюю DLNA, т.ч. стоял еще и вопрос кроссплатформенного просмотра.


15.05.2018

Project Server: ожидание выполнения задачи в очереди

В прошлом году делал внутренний проект по автоматизации работы с корпоративным Project Server. Весьма интересное занятие с учетом того, что некоторые вещи не так однозначны, и не всегда поведение системы соответствует описанному в документации. В процессе работы методом проб и ошибок было получено большое количество наработок, которые могут быть полезны. Вот, например, способ реализации ожидания выполнения задачи в очереди
private void WaitForQueue(Guid jobId)
{
   bool jobDone = false;
   int wait = ServicesManager.QueueSystemClient.GetJobWaitTime(jobId);

   Thread.Sleep(wait * 1000);
   do
   {
      string errorString;
      JobState jobState = ServicesManager.QueueSystemClient.GetJobCompletionState(jobId, out errorString);

      if (jobState == JobState.Success)
      {
         jobDone = true;
      }
      else
      {
         if (jobState.IsInEnumsList(JobState.Unknown, JobState.Failed, 
            JobState.FailedNotBlocking, JobState.CorrelationBlocked, JobState.Canceled))
         {
     throw new Exception("Queue request " + jobState + 
               " for Job ID " + jobId + ".\r\n" + errorString);
         }
         else
  {
     Thread.Sleep(2000);
  }
      }
   } while (!jobDone);
}
Здесь jobId - идентификатор работы, ServicesManager - контейнер подключений к службам служб Project Server (PSI).

14.05.2018

Проблема создания проекта на русском языке в Jira Service Desk

Не так давно настраивал Jira Service Desk и столкнулся с проблемой при создании проекта. Сообщение об ошибке выглядело так:
java.lang.RuntimeException: org.codehaus.jackson.JsonParseException: 
Unexpected character ('П' (code 1055 / 0x41f)): was expecting comma to separate OBJECT entries
 at [Source: java.io.StringReader@1b32752; line: 11, column: 373]
Проблема повторялась до тех пор пока при создании проекта не переключился на английскую локаль в Jira Service Desk. После создания проекта можно снова переключаться на русскую. Это и стало решением.
Немного погуглив, выяснилось, что проблема типовая для русского языка (см. ссылку) и на момент написания данной заметки не исправлена. Т.к. создание проектов у нас не частая операция было принято решение о заведении отдельной учетки под английской локалью по умолчанию только для заведения новых проектов.

12.05.2018

Использование CodeMirror в ASP.NET WebForms приложениях

Несколько лет назад разрабатывал систему на ASP.NET WebForms, в которой расчет ряда значений задавался с помощью формул, формулы описывались языком javascript. Было решено для обработки формул использовать Jurassic, а в качестве визуального редактора использовать CodeMirror. CodeMirror - это классный текстовой редактор, написанный на javascript, для использования на веб-страницах с возможностью расширения. Данный редактор поддерживает возможность подсветки синтаксиса более чем 100 языков программирования.
В целом процесс внедрения CodeMirror в нашу систему проходил успешно, но возникла проблема при использовании его внутри UpdatePanel. Для решения данной задачи был использован следующий хак:
function initializeCodeMirror() {
 var formulaTxt = '<%=FormulaTxt.ClientID%>';
  
 var editor = CodeMirror.fromTextArea(document.getElementById(formulaTxt), {
         leaveSubmitMethodAlone: true,
         lineNumbers: true,
         mode: "javascript",
         theme: 'neat',
         continuousScanning: 500,
         matchBrackets: true,
         continueComments: "Enter",
         extraKeys: {
             "F11": function(cm) {
               cm.setOption("fullScreen", !cm.getOption("fullScreen"));
             },
             "Esc": function(cm) {
               if (cm.getOption("fullScreen")) cm.setOption("fullScreen", false);
             },
             "Ctrl-Q": "toggleComment"
         }
});
  
// Хак для использования CodeMirror в UpdatePanel
window['cmLocalStateEvent'] = function () { editor.save(); };
     
// Хак для отображения контента CodeMirror с учетом интерферирующих скриптов
setTimeout(function() {
 editor.refresh();
}, 0);

28.01.2018

Как сделать блок "Показать полностью" во ВКонтакте без ограничения по количеству символов

Интерфейс создания сообщений в ленте во ВКонтакте позволяет скрывать длинный текст под блоком "Показать полностью". Данная ссылка появляется автоматически, если текст превышает 16384 символов. Тем не менее в ряде случаев возникают ситуации, когда нужно, не захламляя ленту лишним текстом, добавить только небольшую аннотацию, если читателей заинтересует содержимое, то они смогут нажать на ссылку "Показать полностью" и увидеть всю статью. Стандартная механика соц. сети не позволяет этого сделать. Однако можно воспользоваться небольшим трюком добавив символы переноса строки. Избыточные символы переноса будут удалены движком ВК, но при этом будут подсчитаны. С помощью данного трюка легко получить подобную картину:



Пример скрипта можно скачать по ссылке.

04.01.2017

Ошибки проверки сертификации в Sharepoint 2013

В логе Windows наткнулся на часто повторяющуюся ошибку вида "A certificate validation operation took X milliseconds and has exceeded the execution time threshold.  If this continues to occur, it may represent a configuration issue". Хорошее решение данной проблемы представлено здесь.

28.11.2016

SQL: Удаление множественных пробелов внутри строки

Небольшой трюк для удаления множественных пробелов в строке в виде готовой функции для MS SQL Server:
CREATE FUNCTION TrimExtraSpaces 
(
 @Str nvarchar(MAX)
)
RETURNS nvarchar(MAX)
AS
BEGIN
RETURN (SELECT LTRIM(RTRIM(REPLACE(REPLACE(REPLACE(@str,' ','<>'),'><',''),'<>',' '))));
END
GO
Треугольные скобки могут быть заменены на другие символы, если подобное сочетание может встречаться в ваших строках.

13.09.2016

Получение списка всех установленных в Windows программ

Для получения списка всех установленных программ в Windows можно воспользоваться командой PowerShell:

Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | 
Select-Object DisplayName, DisplayVersion, Publisher, InstallDate | Format-Table –AutoSize


Для сохранения в файл можно немного модифицировать команду:


Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | 
Select-Object DisplayName, DisplayVersion, Publisher, InstallDate | Format-Table –AutoSize > {my_file_name}.txt

10.01.2016

SQL: Получение списка недель с номерами

Небольшой скрипт для получения списка недель, их номеров, а также даты начала и конца конкретной недели:
DECLARE @YearNumber char(4) = 2015

DECLARE @Weeks TABLE 
(
   WeekNumber int,
   StartOfWeek datetime,
   EndOfWeek datetime
);

DECLARE @WeekNumber int = 1;
WHILE YEAR(DATEADD(wk, DATEDIFF(wk, 6, '1/1/' + @YearNumber) + (@WeekNumber-1), 6)) <= @YearNumber
BEGIN
    INSERT INTO @Weeks
    VALUES  (
                @WeekNumber,
                DATEADD(wk, DATEDIFF(wk, 6, '1/1/' + @YearNumber) + (@WeekNumber-1), 6),
                DATEADD(wk, DATEDIFF(wk, 5, '1/1/' + @YearNumber) + (@WeekNumber-1), 5)
            )

    SET @WeekNumber = @WeekNumber +1;
END

SELECT *
FROM @Weeks

06.12.2015

Проблемы установки Sharepoint 2013 на Windows Server 2012

При установке Sharepoint 2013 на Windows Server 2012 R2 возникли следующие проблемы и найдены решения:
  1. При запуске Программы подготовки продуктов Microsoft Sharepoint 2013, которая должна установить весь необходимый софт для дальнейшей установки Sharepoint, выдается сообщение "Этот инструмент не поддерживает текущую операционную систему".

    Для решения данной проблемы следует загрузить скрипты для оффлайн установки и загрузки компонентов, доступные по ссылке. После этого запустите скрипты из архива в следующем порядке:
    1. Install-SP2013RolesFeatures.ps1
    2. Download-SP2013PreReqFiles.ps1
    3. Install-SP2013PreReqFiles.ps1

  2. Во время установки Windows Server Appfabric выдается ошибка 1603 или при попытке загрузки запуска установки Sharepoint выдается сообщение "Appfabric is not correctly configured".

    Проблема возникает, если перед установкой компонента был установлен MS SQL Server. После этого нужно найти переменную среды PSModulePath, а в ней удалить пути, которые относятся к SQL Server. После этого следует удалить старую установленную версию Appfabric, и можно попробовать установить снова.

27.07.2014

C#: Получение даты сборки

К сожалению нет простого способа для получения даты выполнения билда .net-сборки, тем не менее наиболее точное значения можно получить с помощью заголовка PE-файла, в который при подликовке проставляется дата:
public static DateTime GetBuildDate()
{
   string filePath = Assembly.GetCallingAssembly().Location;
   const int peHeaderOffset = 60;
   const int linkerTimestampOffset = 8;
   byte[] b = new byte[2048];
   using (Stream s = new FileStream(filePath, FileMode.Open, FileAccess.Read))
   {
      s.Read(b, 0, 2048);
   }

   int secondsSince1970 = BitConverter.ToInt32(b, BitConverter.ToInt32(b, peHeaderOffset) + linkerTimestampOffset);
   DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0);
   dt = dt.AddSeconds(secondsSince1970);
   dt = dt.AddHours(TimeZone.CurrentTimeZone.GetUtcOffset(dt).Hours);
   return dt;
}