Авторизация:

Демков Борис Павлович (borisfox)

Фотография / Юзерпик 28 лет
  • Россия
  • Москва
Просмотры: 0
В сервисе: 1 год 3 месяца
Последний визит: 04.11.2008 в 19:13
Контактные данные

Контактные данные доступны только авторизованным пользователям.


Дополнительная информация / Резюме

Общий стаж работы программистом 5 лет.
Профессиональные навыки:
Опыт разработки на языках:
• C++ > 1 года (MFC, STL)
• C# > 1 года (VSS)
• T-SQL > 1 года (Microsoft SQL Server 2000/2005)
• VBA от 2 лет (MS Word, MS Excel, MS Access)
• Макроязык 1С:Предприятие от 4 лет (7.7, 8.0)
Знакомство с технологиями:
• .NET Framework
• COM
• Multithreading
• Win32 API
Аккуратность и ответственность


Портфолио

1. Альтернатива курсорной обработки данных
Основная идея – использовать переменные в запросе UPDATE для реализации логики алгоритма, что позволяет избежать «медленной» курсорной обработки данных.
Некоторая избыточность переменных объясняется тем, что в запросах только для переменных соблюдается порядок вычислений «сверху-вниз».

DECLARE @NCh smallint
DECLARE @ID smallint
DECLARE @IDCh smallint
DECLARE @NzSm smallint
DECLARE @NC smallint

SET @Nch = 0
SET @ID = 0
SET @NzSm = 0
SET @NC = 0
SET @IDCh = 0

UPDATE arcSmenaCopy

SET @ID = CASE WHEN (@IDCh = ASM.IDCheck) THEN @ID + 1 ELSE 1 END,


@NCh = CASE WHEN (@NzSmASM.ZNumber) OR (@NCASM.NCash) THEN 1 ELSE CASE WHEN @IDCh = ASM.IDCheck THEN @NCh ELSE @NCh + 1 END END,


@NC = ASM.NCash,


@NzSm = ASM.ZNumber,


@IDCh = ASM.IDCheck,


arcSmenaCopy.IDCheck = @NCh,


arcSmenaCopy.[ID] = @ID


FROM arcSmenaCopy


INNER JOIN arcSmena_Sort ASM ON arcSmenaCopy.ZNumber = ASM.ZNumber
AND arcSmenaCopy.NCash = ASM.NCash
AND arcSmenaCopy.IDCheck = ASM.IDCheck
AND arcSmenaCopy.[ID] = ASM.[ID]

2. Взаимодействие между потоками
В ходе реализации проекта было необходимо иметь возможность обращаться к объектам «основного» потока из «дочернего». Сложность заключалась в том, что в этом случае возникает исключение «Cross-thread operation». Платформа .Net Framework считает, что прямой доступ к элементу управления из потока, в котором он не был создан, является не безопасным. Поэтому используем метод Control.Invoke чтобы вызвать наш метод в «основном» потоке.

//функция запускается в отдельном потоке
void Start()
{


Count.Text = "0";


Count.Invalidate();

//для обращения к ресурсам основного потока вызваем
//делегат StartStopTick методом Invoke, иначе возникает ошибка синхронизации!
//функция StartStopTimeMashine запускает таймер


StartStopTick c = new StartStopTick(StartStopTimeMashine);


this.Invoke(c, new object[] {true});


foreach (DataGridViewRow r in ListProg.Rows)


{
int SecLive = ((r.Cells[3].Value == null) || (r.Cells[3].Value.ToString() == "")) ? 0 :
int.Parse(r.Cells[3].Value.ToString());


if ((r.Cells[3].Value == null) ||(r.Cells[2].Value.ToString() == "")) continue;


//каждое приложение страртует в отдельном процессе


ProcApp MyProc = new ProcApp();


MyProc.Proc = new Process();


MyProc.Proc.StartInfo.FileName = r.Cells[2].Value.ToString();


MyProc.Proc.Start();


MyProc.SecLive = SecLive;


AProc.Add(MyProc);


//для вывода сообщений в текстовое окно основной программы


//используем туже методику обратного вызова


SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { "Приложение " + r.Cells[1].Value == null ? "":r.Cells[1].Value.ToString() + " запущено. Время запуска:" + String.Format("{0:T}", DateTime.Now) });


if (SecLive != 0) Thread.Sleep(SecLive * 1000);


}


this.Invoke(c, new object[] {false});
}


3. Использование очереди сообщений для связи событий в Microsoft SQL Server 2005 и приложением Windows Forms
Возможность использования кода, написанного на языках .Net в процедурах и функциях Microsoft SQL Server 2005, позволило мне поднять уровень взаимодействия приложения и базы на более качественный уровень, используя технологию MSMQ.

//Данный код оформляется в виде dll модуля, который импортируется в SQL.
//данный модуль предназначен для вызова из SQL
//средствами SQL CLR
public class SqlCLR
{


/// Посылаем сообщение в очередь


/// Queue path


/// Message


[SqlProcedure]


public static void Send(SqlString queue, SqlString msg)


{


try


{


using (MessageQueue msgQueue = new MessageQueue(queue.ToString(), QueueAccessMode.Send))


{


msgQueue.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) });


msgQueue.Send(msg.Value);


}


}


catch


{


}


}
}

В SQL создается хранимая процедура
CREATE PROCEDURE dbo.p_MSMQSend
@queue nvarchar(200),
@msg nvarchar(MAX)
AS EXTERNAL NAME SqlModule.SqlCLR.Send
GO

В триггере вызывается данная процедура
-- =============================================
-- Author: demkov
-- Create date: 01.10.07
-- Description: Посылаем сообщение
-- =============================================
ALTER TRIGGER [dbo].[Изменения] ON [dbo].[ОчередьКоманд] FOR UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;


IF UPDATE(Состояние)
BEGIN


DECLARE @ИмяОчереди nvarchar(256)
--откроем курсор только по выполнненым сторкам и отправим сообщения
DECLARE Строки CURSOR LOCAL FOR SELECT
'.\private$\' + ISNULL(Inserted.ИмяФайла,'') AS ИмяОчереди
FROM Inserted
WHERE ISNULL(Inserted.Состояние,0) = 3


OPEN Строки
FETCH NEXT FROM Строки
INTO @ИмяОчереди


WHILE (@@FETCH_STATUS = 0 )
BEGIN


EXEC p_MSMQSend @ИмяОчереди, 'Выполнил'


FETCH NEXT FROM Строки
INTO @ИмяОчереди


END
CLOSE Строки
DEALLOCATE Строки

END

END

4. Синтаксический разбор выражения методом конечных автоматов.
Данный алгоритм был применен для создания вычислителя выражений, который оформлен в виде ActiveX элемента. Вся логика заключается в отдельном классе Calc. В качестве примера приведу его основную функцию.

vector Calc::Calculate(CString & s){

//очищаем стек операций, данных и массив данных
m_data.clear();
m_sdata.clear();
m_soper.clear();


int ko = 0;
int kz = 0;

//int k;
vector res;
if (s.Trim().IsEmpty()) return res;
vector::iterator k; //указатель на выделенную операцию
vector::iterator kp; //указатель на переменную
oper CurrOper; //текущая операция в стеке
CString str;


var v1, v2;


var R; //рабочая ячейка
//инциализация таблицы конечного автомата
const char Tab[7][12] = { {0 ,1 ,2 ,5 ,4 ,3 ,-8 ,3 ,3 ,0 ,7 ,7 } , {-1 ,1 ,1 ,-1 ,-1 ,-1 ,-8 ,-8 ,-8 ,-1 ,-1 ,-1 } ,
{-2 ,-8 ,2 ,-2 ,-8 ,-2 ,6 ,-2 ,-2 ,-2 ,-2 ,-2 } , {-3 ,-3 ,-3 ,-8 ,-8 ,3 ,-8 ,-8 ,-8 ,-6 ,-6 ,-6 } ,
{-4 ,-4 ,-4 ,-8 ,-4 ,-4 ,-8 ,-8 ,-8 ,-6 ,-6 ,-6 } , {-5 ,-5 ,-5 ,-5 ,-8 ,-5 ,-8 ,-8 ,-8 ,-5 ,-5 ,-5 } ,
{-2 ,-8 ,6 ,-2 ,-8 ,-2 ,-8 ,-8 ,-8 ,-2 ,-2 ,-2}};

const char * alf = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789)(.,;\r\n";


const char alf1[71] = {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,


1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,


2,2,2,2,2,2,2,2,2,2,3,4,6,7,8,9,10,11};


int kol = 0; int p = 0; int poz = 0;
for (int i=0;i