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