четверг, 26 августа 2010 г.

Работа с партициями в MSAS 2008

 

Всем привет.

Сегодня хочу описать  небольшой скрипт, который я написал для работы с партициями MSAS.

Предыстория

У нас на предприятия есть отчетная система(язык не поворачивается назвать ее аналитической), построенная на основе MSAS. Так вот  в чем состояла наша проблема. Вытяжка в таблицу фактов за весь период работы предприятия была, есть и будет очень долго, где-то примерно 10 часов, поэтому чтоб не запускать ее каждый раз решили перейти к партициям в кубе. Каждый год у нас считается что-то типа закрытого периода, обновляются только текущий месяц и предыдущий. Остальные партиции  обновляются, только в случае непредвиденных обстоятельств. В MSAS все это выглядит вот так:

as1

Для каждой партиции указан источник:

SELECT *   FROM [dbo].[таблица]   WHERE year(Дата)<=2004

То есть фактически каждая партиция содержит данные за определенный год. Что же касается текущего то, тут чуть другая ситуация.

Для текущего года, на картинки part_2010 источник  другой

SELECT   * FROM  [dbo].[таблица]
  WHERE
(Year(Дата)=2010 ) and   ( (Month(Дата)>=1) and  (Month(Дата)<=6))

а партиция prev  содержит источник за предыдущий месяц и current за текущий.

Такая структура  позволяет обновлять только  2 партиции(текущую и предыдущую) и отказаться от полного процессинга куба.

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

Задача

Необходимо написать скрипт, который бы создавал новую партицию и изменял бы в источнике данных запрос

Решение

Решением стал  скрипт, написанный на C# с использованием AMO

   1: public void Main()
   2:        {
   3:            // TODO: Add your code here
   4:            Dts.TaskResult = (int)GetAS();
   5:        }
   6://создание партиции год
   7:        public bool CreatePartitionYear(Cube cubePartition)
   8:        {
   9:            Partition partYear = new Partition("part_" + DateTime.Now.Year.ToString());//создаем объект партиции и назвначаем ему имя
  10:            Microsoft.AnalysisServices.QueryBinding query = new QueryBinding();// создаем объект, отвечающий за источник
  11:            query.DataSourceID = cubePartition.DataSource.ID;//указываем  id источника
  12:            partYear.StorageMode = StorageMode.Molap;//указываем тип партции
  13:            query.QueryDefinition = "SELECT  * FROM [dbo].[таблица] WHERE (Year(Дата)=" + DateTime.Now.Year.ToString() + " ) and   (Month(Дата)=1) ";//указываем собственно запрос
  14:            partYear.Source = query;// присваевается объект источника  партиции
  15:            try
  16:            {
  17:                cubePartition.MeasureGroups[0].Partitions.Add(partYear);//добавляем партицию в куб
  18:                partYear.Update();//отправляем новое определение объекта на сервер
  19:                partYear.Update(UpdateOptions.AlterDependents);// на всякий случай
  20:                cubePartition.MeasureGroups[0].Update(UpdateOptions.AlterDependents);//обновляем структуру секций
  21:                cubePartition.Update();//обновляем  структуру куба
  22:                cubePartition.Refresh();//делаем синхронизацию объектов  Amo и as
  23:                cubePartition.MeasureGroups[0].Refresh();//делаем синхронизацию объектов  Amo и as
  24:            }
  25:            catch (Exception exp)
  26:            {
  27:                return false;
  28:            }
  30:            Partition partNew;
  32:            partNew = cubePartition.MeasureGroups[0].Partitions.FindByName("prev");// ищем  партицию prev
  33:            try
  34:            {
  35:                if (partNew != null) partNew.Drop();//если существуе, удаляем
  36:            }
  37:            catch (Exception exp)
  38:            {
  40:            }
  41:            partNew = cubePartition.MeasureGroups[0].Partitions.Add("prev");// добавляем партицию
  42:            partNew.StorageMode = StorageMode.Molap;// указываем тип партции
  43: /создаем запрос для источника партиции
  44:            Microsoft.AnalysisServices.QueryBinding queryPrev = new QueryBinding();
  45:            queryPrev.QueryDefinition = "SELECT  * FROM [dbo].[Таблица] WHERE (Year(Дата)=" + DateTime.Now.Year.ToString() + " ) and   (Month(Дата)=" + (DateTime.Now.Month - 1).ToString() + ") ";
  46:            queryPrev.DataSourceID = cubePartition.DataSource.ID;
  47:            partNew.Source = queryPrev;
  49:            partNew.Update();//обновляем структур
  50:            cubePartition.MeasureGroups[0].Update(UpdateOptions.AlterDependents);//обновляем структуру секций
  51:            cubePartition.Update();//обновляем структуру куба
  52:            cubePartition.Refresh();//синхронизируем объекты
  53:            cubePartition.MeasureGroups[0].Refresh();//синхронизируем объекты         
  54:            return true;
  55:        }
  56: /создание партиции месяц
  57:        public bool CreatePartitionMonth(Cube cubePartition)
  58:        {
  59:            Partition part = cubePartition.MeasureGroups[0].Partitions.FindByName("part_" + DateTime.Now.Year.ToString());//ищем партцию текущего года
  60:            if (part != null)
  61:             {
  62:                        Partition partPrev = cubePartition.MeasureGroups[0].Partitions.FindByName("prev");//ищем партицию prev
  63:                        List<Partition> lspPart = new List<Partition>();//список партиций
  64:                        Microsoft.AnalysisServices.QueryBinding query = new QueryBinding();//объект  источник для партиции года
  65:                        query.DataSourceID = cubePartition.DataSource.ID;
  66:                        if ((DateTime.Now.Month == 1))//проверка на месяц
  67:                        {
  68: //Сделано для того, чтобы не возникала ситуация 1-2(текущий месяц январь(01, то есть 1), для вычисления  месяца, который был 2 месяца назад, то есть 1-2=-1 и получаем exception. Да можно было бы от этого избавится и использовать функции месяца и вычислять минус 62 дня, но так наглядней и понятней
  69:                            query.QueryDefinition = "SELECT  * FROM [dbo].[таблица] WHERE (Year(Дата)=" + (DateTime.Now.Year-1).ToString() + " ) and   (Month(Дата)=11) ";
  70:  
  71:                        }
  72:                        else
  73:                        {
  74:                            if ((DateTime.Now.Month == 2))//проверка на второй месяц. 
  75:                            {
  76:                                query.QueryDefinition = "SELECT  * FROM [dbo].[таблица] WHERE (Year(Дата)=" + (DateTime.Now.Year - 1).ToString() + " ) and   (Month(Дата)=12) ";
  77:                            }
  78:                            else
  79:                            {
  80:                                query.QueryDefinition = "SELECT  * FROM [dbo].[таблица] WHERE (Year(Дата)=" +
  81:                                    DateTime.Now.Year.ToString() + " ) and   ((Month(Дата)>=1) and (Month(Дата)<=" + (DateTime.Now.Month - 2).ToString() + ")) ";
  82:                            }
  83:                        }
  84:                        part.Source = query;
  86:                 lspPart.Add(partPrev);
  88:                        try
  89:                        {
  90:                            part.Merge(lspPart);//сливаем партиции
  91:                            part.Update(UpdateOptions.AlterDependents);//обновляем структуру секции год
  92:                            cubePartition.MeasureGroups[0].Update(UpdateOptions.AlterDependents);//обновляем структуру секций
  93:                            cubePartition.Update();//обновляем структур куба
  94:                            cubePartition.Refresh();//синхронизация
  95:                            cubePartition.MeasureGroups[0].Refresh();//синхронизация
  97:                        }
  98:                        catch(Exception exp)
  99:                        {
 100:                            string message = exp.Message;
 101:                            return false;
 102:                        }
 104:                        try
 105:                        {
 106:              //здесь создаем партицию prev             
 107:                             Partition partNew;
 108:                            
 109:                            partNew =cubePartition.MeasureGroups[0].Partitions.FindByName("prev");
 110:                            try
 111:                            {
 112:                                if (partNew != null) partNew.Drop();
 113:                            }
 114:                            catch (Exception exp)
 115:                            {
 116:                                
 117:                            }
 118:                            partNew = cubePartition.MeasureGroups[0].Partitions.Add("prev");
 119:                            partNew.StorageMode = StorageMode.Molap;
 120:                            
 121:                            Microsoft.AnalysisServices.QueryBinding queryPrev = new QueryBinding();
 122:                            queryPrev.QueryDefinition = "SELECT  * FROM [dbo].[таблица] WHERE (Year(Дата)=" + DateTime.Now.Year.ToString() + " ) and   (Month(Дата)=" + (DateTime.Now.Month - 1).ToString() + ") ";
 123:                            queryPrev.DataSourceID = cubePartition.DataSource.ID;
 124:                            partNew.Source = queryPrev;
 126:                            partNew.Update();
 127:                            cubePartition.MeasureGroups[0].Update(UpdateOptions.AlterDependents);
 128:                            cubePartition.Update();
 129:                            cubePartition.Refresh();
 130:                            cubePartition.MeasureGroups[0].Refresh();
 132:                        }
 133:                        catch (Exception exp)
 134:                        {
 135:                            string message = exp.Message;
 136:                            return false;
 137:                        }
 139:             }
 140:             return true;
 141:        }
 142:  
 143:/ /процессинг партиций
 144:        public bool ProccesPartition(Cube cubePartition)
 145:        {
 146:            Partition partPrev = cubePartition.MeasureGroups[0].Partitions.FindByName("prev");//ищем партицию
 147:            if (partPrev != null)
 148:            {
 149:                partPrev.Process(ProcessType.ProcessFull);//делаем полный процессинг
 150:            }
 151:            else
 152:            {
 153:                return false;
 154:            }
 156:            Partition parCurrent = cubePartition.MeasureGroups[0].Partitions.FindByName("current");//ищем партицию
 157:            if (parCurrent != null)
 158:            {
 159:                parCurrent.Process(ProcessType.ProcessFull);//полный процессинг
 160:  
 161:            }
 162:            else
 163:            {
 164:                return false;
 165:            }
 167:            return true;
 169:        }
 170:  
 172:        public int GetAS()
 173:        {
 174:            using(Server srv=new Server())
 175:            {
 176:                srv.Connect("localhost");//коннектимся к серверу
 177:                Database db = srv.Databases.GetByName("ИмяБазы");//конектимся к базе
 178:                if (db != null)
 179:                {
 180:                    Cube cubeOverturn = db.Cubes.GetByName("ИмяКубика");//ищем кубик
 181:                    if (cubeOverturn != null)
 182:                    {
 183:                        DateTime dt = DateTime.Now;//определяем текущее время
 184:                        if (dt.Day == 1)
 185:                        {
 186:                            if (dt.Month == 3)
 187:                            {
 188:                                if (!CreatePartitionYear(cubeOverturn))//создаем партцию года
 189:                                {
 190:                                    srv.Disconnect();
 191:                                    return (int)ScriptResults.Failure;
 192:                                }
 193:                                else
 194:                                {
 195:                                    ProccesPartition(cubeOverturn);//процессим партиции
 196:                                }
 197:                            }
 198:                            else
 199:                            {
 200:                                if (!CreatePartitionMonth(cubeOverturn))//создаем партиции месяца
 201:                                {
 202: /произошла ошибка
 203:                                    srv.Disconnect();//разрываем связь
 204:                                    return (int)ScriptResults.Failure;//возвращаем fail
 205:                                }
 206:                                else
 207:                                {
 208:                                    ProccesPartition(cubeOverturn);//процессим
 209:                                }
 210:                            }
 211:                        }
 212:                        else
 213:                        {
 214:                            if (!ProccesPartition(cubeOverturn))//просто процессим
 215:                            {
 216:                                srv.Disconnect();
 217:                                return (int)ScriptResults.Failure;
 218:                            }
 220:                        }
 221:                    }
 222:                    else
 223:                    {
 224:                        srv.Disconnect();
 225:                        return (int)ScriptResults.Failure;
 226:                    }
 228:                }
 229:                else
 230:                {
 231:                    srv.Disconnect();
 232:                    return (int)ScriptResults.Failure;
 233:                }
 234:                srv.Disconnect();
 235:            }
 238:            return (int)ScriptResults.Success;
 239:        }
 242:    }

Да, я знаю, что код можно было бы упростить. Сделать рефакторинг, но  этот будет все потом(нет времени). Сейчас скрипт работает нормально на  моей базе.

пятница, 16 апреля 2010 г.

Setup Project в Visual Studio 2008

Всем привет.

Я сейчас работаю над созданием инсталлятора с помощью VS 2008, встретился с большим количеством проблем, вот поэтому и решил начать небольшой цикл записей о работе с Setup Project.

Почему Setup Project в VS?

Почему Setup Project, а не WIX или NSIS или InstallShield?  Потому что Setup Project во  первых встроен в VS, во вторых для action можно использовать скрипты, написанные на C# и т.д. языках, а в третьих часть нудной работы типа, указать куда должен сохраняться файл, где должна создаваться директория, проверяться наличие нужных библиотек и т.д. Это конечно для кого-то не аргументы.  Однако, инсталлятор InstallShield – платный, инсталлятор NSIS – требует знание скриптового языка, WIX – эх, WIX это конечно “ВЕСЧЬ”, но он не для начинающих, это для профи, которым не лень набирать уйму кода и которые хотят сконфигурировать очень тонко инсталлятор своего приложения. Возможно когда-нибудь я расскажу про него. Ну, а теперь приступим к созданию нашего инсталлятора.

Начинаем….

Возьмем любой windows проект. Я быстренько создал windows проект. Теперь делаем следующие добавляем Setup Project в solution

project

В Solution у нас появляется новый проект

solution

 

И открывается раздел File System. В данном разделе происходит добавление  файлов, которые необходимо установить, а также ярлыков на рабочий стол и  ярлыки в меню Пуск->Программы. Смотрите на рисунке File System on Target Machine:

  1. Application Folder –папка, которые содержит файлы для установки
  2. User’s desktop – в данном разделе, будут содержаться файлы, которые появятся у пользователя на рабочем столе(в основном  ярлыки)
  3. User’s Programs Menu – в данном разделе, будут содержаться файлы, которые появятся у пользователя в меню пуск(в основном  ярлыки)appl

Начнем добавлять файлы

1 Добавляем  файл lesson.exe в инсталлятор

addfiles

addfiles1

addfiles3

2 Дальше, хотим, чтобы  у нас появилась иконка на рабочем столе. Делаем или выбираем иконку формат ico. Вначале иконку необходимо добавить в application folder, как сделали в предыдущем шаге. После чего правой кнопкой на Users Desktop и выбираем Create Shortcut to User’s Desktop и называем объект, который появится в правой стороне(красная стрелка на картинке ниже), Lesson

icons

Правой кнопкой мыши нажимаем на  Lesson и выбираем свойства(Properties), в свойствах выбираем Icon, нажимаем на кнопку и выбираем Browse, в появившемся окне ICON, нажимаем на Browse

icons2

В окне Select Item in Project выбираем Application Folder,  после чего выбираем наш файл иконки и нажимаем ОК, в окне Icon  появится наша иконка, выбираем ее и нажимаем OK.

icons3

Точно таким же образом добавляем нашу иконку в Пуск, только выбираем не User’s Desktop, а User’s Programs Menu.

В принципе наш установщик готов, можно откомпилировать проект и  получить установочный файл.

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

Ну вот на этом все, пока. Продолжение следует……

четверг, 15 апреля 2010 г.

Я вернулся

Вот решил восстановить свой блог। Да записей у меня здесь немного, но все таки есть। За эти два года накопилось много материала, надо все как-то упорядочить। Но самое главное, я понимаю, что я начинаю тормозить в своем развитии на своей фирме, к сожалению сейчас я не могу уволится, на то есть несколько причин। Поэтому решил упорядочить свои знания и выкладывать их виде записей блога। Что же произошло за эти 2 года, ну все по порядку। Во первых я поднабрался опыта, работал с американцами и россиянами, разработал несколько порталов, но об этом напишу позже। Во вторых, я наконец-то перевел аналитику на своей фирме на MSAS2008 В третьих, начал работать с DNN, да был у меня с ним еще тот гемморой। В четвертых наконец то перевел сайт фирмы на SQL2005 и на IIS 7.० и на ASP.net 3.5 И еще много чего, ну в общем все по порядку। Всем кто читал мои статьи всем большое спасибо। И тем кто присоединился ко мне за время моего отсутствия в блоге

четверг, 12 июня 2008 г.

MS AS 2000 VS дисковая подсистема(или как я искал ошибку, там где ее нет)

Недавно на одном из филиалов фирмы, где я работаю, начали падать кубы. Происходило это очень странно: во-первых в сообщениях об ошибках выдается, что ось залочена или повреждена. во-вторых происходила перезагрузка AS при попытке перепроцессить куб. Начал разбираться в чем проблема. Захожу в сам куб(editor) все нормально, куб открывается, browse осей работает. Пытаюсь процессить - выдает ошибку. Делаю одну интересную вещь, посдмотренную на www.sql.ru, убиваю все файлы в папке Data/Название базы. Делаю перепроцессинг, все равно падает. Беру накатываю backup и процешу и ву аля работает. Работает, это конечно хорошо. Но причину сбоя я не нашел. Начинаю дальше искать эту проблему. И тут меня озаряет, а может это проблема не в Олапе, а может это проблема в железе. Начинаю тестировать дисковую подсистему, нагружаю ее по полной. И вот при тестирование происходит зависание сервера, после чего машину можно перегрузить, только толкнув кнопку reset на башне. Перегружаю и запускаю процессинг, и вот она родимая ошибочка. Переношу всю папку DATA на другой раздел диска, который относится к другому винту. И запускаю процессинг, он отрабатывает нормально. Уже как 3 дня полет нормальный(Тьфу, тьфу, тьфу). Вот так вот весело, кто кого Олап или дисковая подсистема?

вторник, 3 июня 2008 г.

О фрилансе

Сейчас каждый пишет о этом виде работы и я тоже внесу свою лепту. Мои советы начинающим:
  1. Всегда прежде чем начинать работу ТРЕБУЙТЕ ТЕХНИЧЕСКОЕ ЗАДАНИЕ или составляйте его сами. Никогда не начинайте работу без него, когда будете сдавать работу этот документик позволит вам избежать споров с заказчиком по поводу заказа. Также было бы не плохо, чтоб под ТЗ стояла ваша подпись и подпись заказчика(конечно супер было бы, если бы там еще стояла печать заказчика, ну если это возможно). Также в ТЗ поставте сроки начала работы и сроки окончания.
  2. Заключайте договор на работу, где будут описаны сроки, сумма за работу, предоставления кода, передача авторских прав и т.д. То есть в договор необходимо включить, все что касается юридической стороны, заметьте не технической, а именно юридической.
  3. Поищите информацию про вашего заказчика в инете, благо сейчас люди в сети оставляют много информации о себе, например в социальных сетях, на форумах и т.д. Это позволит вам оценить своего заказчика и сделать выводы по поводу работы с ним. Да еще не забывайте заходить на форумы таких сайтов, как weblancer, freelancehunt
  4. Если устраиваетесь на постоянную удаленную работу, не советую вам сочетать основную работу и удаленную, через месяц выдохнитесь (на своем опыте знаю)
Ну вот это основное, да еще почитайте вот на этом блоге рекомендации по freelancer, там конечно не много, но в самую точку. Эта рекомендация тоже является главной, если не основной, при работе с клиентами. Конечно я буду дополнять рекомендации и советы по freelancer из своего личного опыта.

среда, 28 мая 2008 г.

Установка SQl Server 2005 на Windows Server 2008

Вот столкнулся с такой проблемой. Пытаюсь установить SQL, а он не может определить OC. Начал искать по русскоязычным сайтам и ничего, может плохо искал, а может действительно ничего. Меня конечно же это удивило, при чем очень. Ну не может быть такого, что никто из наших не устанавливал SQL на Win 2008. Ну ладно. Пришлось искать на англоязычных сайтах. Нашел вот здесь, оказывается надо было скачать hotfix с сайта Microsoft. И вуаля установилось