Контактные данные
Данные не опубликованы.
Дополнительная информация / Резюме
Общий стаж работы программистом 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