Главная страница статей --> Хитрости при программировании php, заметки по базам данных

Сложные графики и диаграммы в ASP.NET. Часть пятая – интерактивность.

Источник: realcoding.net

Введение


В предыдущей статье речь шла об использовании диаграмм ChartSpace, входящих в состав библиотеки owc11. Мы продолжим изучение этой библиотеки, но в более сложном применении. В данном случае нас интересует интерактивность (то есть обратная связь). Только представьте себе: пользователь увидел круговую диаграмму, нажал мышью по интересующему его сектору, и тут же получил на месте круговой диаграммы гистограмму. Причём гистограммы выводятся разные – для каждого сектора свои. Дальше можно щёлкать уже гистограмму – и в зависимости от выбранного ряда столбиков получить ту или иную реакцию сервера. На что реагирует сервер? На цвет нажатой точки. Чтобы воплотить эту мысль, нам придётся основательно пересмотреть работу с ChartSpace, выделив процедуру работы с базой данных в отдельный кодовый класс (в VB есть также специальный тип кодовых классов – модули – они проще в обращении). Нам также придётся изучить вопросы передачи информации от класса к классу, узнать побольше о цветах, и соответственно глубже копнуть библиотеку owc11.

Схема работы


Рассмотрим схему взаимодействия Вэб-страницы, содержащей диаграмму, с другими модулями (рис. 1.)



Рис. 1. Необходимые составляющие и как они связаны.

Из рисунка видно, что схема работы расширилась относительно того, как это было в 4-й статье. В 4-й статье я постарался как можно больше упростить схему, чтобы читатели быстрее вникли: работа с базой данных велась прямо через ChartSpace. Теперь же шире задачи – соответственно шире схема работы. На самом деле текущая 5-я статья ближе к реальному проекту, так как проекты, использующие диаграммы, обычно довольно наворочанные. Тем не менее, эта схема гораздо проще тех, что используют элементы управления диаграммами сторонних разработчиков. Да и гораздо надёжнее: тут Вы не зависите от ошибок и ограничений сторонних разработчиков. Ну и гораздо дешевле: библиотека owc11 является бесплатным приложением к пакету MS Office, тогда как за библиотеку вроде Infragistics, Component One и им подобных, Вам придётся раскошелиться на $1000 (пиратские версии стоят дёшево, но более сложны в применении, так как время от времени их приходится лечить от лицензионного синдрома).

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

1. Сессий может быть очень много, поэтому в сессии хранить объёмные данные не рекомендуется. Я всегда выступал против хранения там чего бы то ни было кроме небольших строковых данных.
2. Массивы байтов могут занимать много памяти, а память на сервере не резиновая. Опыт разработки показывает, что хранение большого объёма данных в общих переменных, например результатов запросов к БД, содержащих десятки тысяч строк, приводит к неожиданным сбоям – переменные просто обнуляются! Сайт может работать какое-то время, а потом бац – и ошибка времени выполнения типа «обращение к переменной, в которой кроме NULL ничего нет». И это на сервере, имеющем 1G памяти! Причём, я уверен, что и 100G не спасут: ASP.NET обладает какими-то предельными границами (порядка 100M) вроде того, как это было в DOS-версии Бэйсика. Только средствами самого Бэйсика можно было установить предельный размер памяти. К сожалению, в ASP.NET такой возможности нет, поэтому к использованию памяти следует относиться очень бережно, экономить каждый килобайт.

Структура программы


Представим схему, изображённую на рис. 1., в более приближённом к коду виде (рис. 2.)



Рис. 2. Реализация интерактивности с помощью библиотеки кодовых классов.

Примечание

В литературе по программированию часто заходит речь о трёхуровневом программировании. Как нетрудно догадаться, рассматриваемая библиотека кодовых классов представляет из себя второй уровень (рис. 3)



Рис. 3. Трёхуровневое представление программы.


Библиотека классов Class1.cs

Рассмотрим листинг этой библиотеки. Обратите внимание на комментарии, они Вам помогут понять как чего работает. Для наглядности код раскрашен с помощью Студии VS.NET 2005.

using System;
 
using System.Web;
 
using System.Data;
 
using System.Data.SqlClient;
 
namespace MaxPro
 
{
         
public class All//простые функции
         
{
               
//var
               
public const Int32 iMaxInt32=2147483647;
               
//end var
               // Функция IsNull как в VB6, переваривает любые типы
               
public static Boolean IsNull(Object oObject)
               {
                      if(
oObject==null oObject==DBNull.Value) return true; else return false;
               }
               
// Функция IsNumeric, переваривает любые типы
               
public static Boolean IsNumeric(Object oObject)
               {
                      if(
IsNull(oObject)) return false;
                     
try//проверка на число
                     
{
                            
Convert.ToDecimal(oObject);
                             return
true;
                      }
                     
catch
                     
{
                             return
false;
                      }
               }
               
// Функция IsByte, переваривает любые типы
               
public static Boolean IsByte(Object oObject)
               {
                      if(
IsNull(oObject)) return false;
                     
try//проверка на число типа байт
                     
{
                            
Convert.ToByte(oObject);
                             return
true;
                      }
                     
catch
                     
{
                             return
false;
                      }
               }
               
// Функция, проверяющая совпадение цветов. Переваривает любые типы
               
public static Boolean bColor(Object oR1,Object oG1, Object oB1,Object oR2,Object oG2, Object oB2)
               {
                      if(!
IsByte(oR1) !IsByte(oR2) !IsByte(oG1) !IsByte(oG2) !IsByte(oB1) !IsByte(oB2)) return false;
                     
//var
                     
Double dR1=Convert.ToDouble(oR1);//красный1
                     
Double dG1=Convert.ToDouble(oG1);//зелёный1
                     
Double dB1=Convert.ToDouble(oB1);//синий1
                     
Double dR2=Convert.ToDouble(oR2);//красный2
                     
Double dG2=Convert.ToDouble(oG2);//зелёный2
                     
Double dB2=Convert.ToDouble(oB2);//синий2
                     
Double dTanA1=dG1/dR1;//1-й цвет, тангенс альфа=g/r
                     
Double dTanB1=dB1/dR1;//1-й цвет, тангенс бета=b/r
                     
Double dTanG1=dB1/dG1;//1-й цвет, тангенс гама=b/g
                     
Double dTanA2=dG2/dR2;//2-й цвет, тангенс альфа=g/r
                     
Double dTanB2=dB2/dR2;//2-й цвет, тангенс бета=b/r
                     
Double dTanG2=dB2/dG2;//2-й цвет, тангенс гама=b/g
                     
Double dD=.1;//отклонение (дельта) в долях единицы от цветов в условных обозначениях
                     
Double dDa;//=Abs(1-dTanA1/dTanA2)
                     
Double dDb;//=Abs(1-dTanB1/dTanB2)
                     
Double dDg;//=Abs(1-dTanG1/dTanG2)
                      //end var
                     
dDa=Convert.ToDouble(Math.Abs(1-dTanA1/dTanA2));
                     
dDb=Convert.ToDouble(Math.Abs(1-dTanB1/dTanB2));
                     
dDg=Convert.ToDouble(Math.Abs(1-dTanG1/dTanG2));
                      if(
dDa<=dD && dDb<=dD && dDg<=dD) return true; else return false;
               }
               
// Функция заполнения объектного массива CommandType.StoredProcedure()
               
public static Int32 iZap0(String sConnection,String sProcedure,out Object[,] oZap,out Exception oErr)
               {
                     
//var
                     
Int32 iReturn=-1;
                     
Int32 iX=0;
                     
Int32 iY=0;
                     
Int32 iXmax=0;
                     
Int32 iYmax=0;
                     
SqlConnection oConnection=new SqlConnection(sConnection);
                     
SqlCommand oCommand=new SqlCommand();
                     
SqlDataReader oReader;
                     
System.Collections.ArrayList[] oCol;
                     
//end var
                     
oErr=null;
                     
oCommand.CommandType=CommandType.StoredProcedure;
                     
oCommand.CommandText=sProcedure;
                     
oCommand.Connection=oConnection;   
                     
try
                     
{
                            
oConnection.Open();
                            
oReader = oCommand.ExecuteReader();
                            
iXmax = oReader.FieldCount;
                             if(
iXmax<=0) throw(new Exception(iXmax+ колонок.));
                            
oCol=new System.Collections.ArrayList[iXmax];
                             for(
iX=0;iX<=iXmax-1;iX++)
                             {
                                    
oCol[iX]=new System.Collections.ArrayList();
                             }
                            
iY=-1;
                             while(
oReader.Read())
                             {
                                    
iY+=1;
                                    if(
iY<iMaxInt32)
                                    {
                                          
iYmax=iY+1;
                                          for(
iX=0;iX<=iXmax-1;iX++)
                                          {
                                                
oCol[iX].Add(oReader[iX]);
                                          }
                                    }
                                    else
                                    {
                                          
throw(new Exception(iY+ строк (>=2 147 483 647).));
                                   }
//end if
                            
}//end while
                            
oZap=new Object[iXmax,iYmax];
                             for(
iX=0;iX<=iXmax-1;iX++)
                             {
                                    for(
iY=0;iY<=iYmax-1;iY++)
                                    {
                                          
oZap[iX,iY]=oCol[iX][iY];
                                    }
                             }
                            
oReader.Close();
                            
oReader=null;
                            
oCommand=null;
                      }
                     
catch(Exception oError)
                      {
                            
oZap=new Object[0,0];
                            
oErr=oError;
                            
iYmax=-1;
                      }
                     
finally
                     
{
                             if(!(
oConnection==null))
                             {
                                    
oConnection.Close();
                                    
oConnection=null;
                             }
                      }
                     
iReturn=iYmax;
                      return
iReturn;
               }
         }
         
public class Ow//работа с БД ИмяКаталога на 10.20.30.40 (DataBaseConnectionN)
         
{
               
//var
               
public const String sConnection=user id=ИмяПользователя; password=Пароль; data source=10.20.30.40;initial catalog=ИмяКаталога;
               
//end var
               // Функция заполнения объектного массива CommandType.StoredProcedure()
               
public static Int32 iZap0(String sProcedure,out Object[,] oZap,out Exception oErr)
               {
                      return
All.iZap0(sConnection,sProcedure,out oZap,out oErr);
               }
         }
         
public class Chart//работа с ChartSpace
         
{
               
/* String sCategories=значение1+СимволТабуляции(символ с кодом 9)+значение2+...
                * String sValues=значение1+СимволТабуляции(символ с кодом 9)+значение2+...
                */ //В VB6 также вместе со строками через табулятор поддерживаются одномерные массивы
               //var
               
public const String sProcedure001=Procedure121;
               
public const String sProcedure002=Procedure122;
               
public const String sProcedure003=Procedure123;
               
public const String sProcedure004=Procedure124;
               
public const String sProcedure005=Procedure125;
               
public static Int32 iDataLiteral=Convert.ToInt32(OWC11.ChartSpecialDataSourcesEnum.chDataLiteral);
               
public static Object[,] _oZap001;
               
public static Object[,] _oZap002;
               
public static Object[,] _oZap003;
               
public static Object[,] _oZap004;
               
public static Object[,] _oZap005;
               
//end var
               //property
               
public static Object[,] oZap001
               
{
                     
//var
                      //end var
                     
get
                     
{
                            
Int32 iNum=0;
                            
Exception oErr;
                             if(
_oZap001==null)
                             {
                                    
iNum=Ow.iZap0(sProcedure001,out _oZap001,out oErr);
                                    if(
iNum<=0)
                                    {
                                          
_oZap001=null;
                                    }
                             }
                             return
_oZap001;
                      }
               }
               
public static Object[,] oZap002
               
{
                     
//var
                      //end var
                     
get
                     
{
                            
Int32 iNum=0;
                            
Exception oErr;
                             if(
_oZap002==null)
                             {
                                    
iNum=Ow.iZap0(sProcedure002,out _oZap002,out oErr);
                                    if(
iNum<=0)
                                    {
                                          
_oZap002=null;
                                    }
                             }
                             return
_oZap002;
                      }
               }
               
public static Object[,] oZap003
               
{
                     
//var
                      //end var
                     
get
                     
{
                            
Int32 iNum=0;
                            
Exception oErr;
                             if(
_oZap003==null)
                             {
                                    
iNum=Ow.iZap0(sProcedure003,out _oZap003,out oErr);
                                    if(
iNum<=0)
                                    {
                                          
_oZap003=null;
                                    }
                             }
                             return
_oZap003;
                      }
               }
               
public static Object[,] oZap004
               
{
                     
//var
                      //end var
                     
get
                     
{
                            
Int32 iNum=0;
                            
Exception oErr;
                             if(
_oZap004==null)
                             {
                                    
iNum=Ow.iZap0(sProcedure004,out _oZap004,out oErr);
                                    if(
iNum<=0)
                                    {
                                          
_oZap004=null;
                                    }
                             }
                             return
_oZap004;
                      }
               }
               
public static Object[,] oZap005
               
{
                     
//var
                      //end var
                     
get
                     
{
                            
Int32 iNum=0;
                            
Exception oErr;
                             if(
_oZap005==null)
                             {
                                    
iNum=Ow.iZap0(sProcedure005,out _oZap005,out oErr);
                                    if(
iNum<=0)
                                    {
                                          
_oZap005=null;
                                    }
                             }
                             return
_oZap005;
                      }
               }
               
//end property
               // Процедура заполнения категорий и значений из массива
               
public static void Zap2String(Object[,] oZap,out String sCategories,out String sValues)
               {
                     
//var
                     
Int32 i=0;
                     
Int32 iNum=0;
                     
//end var
                     
sCategories=;
                     
sValues=;
                      if(
oZap==null)
                      {
                            
sCategories=Ошибка БД;
                            
sValues=0;
                             return;
                      }
                     
iNum=oZap.GetLength(1);//число строк
                     
if(iNum<=0)
                      {
                            
sCategories=Пусто;
                            
sValues=0;
                             return;
                      }
                      for(
i=0;i<=iNum-1;i++)
                      {
                             if(
i==iNum-1)
                             {
                                    
sCategories+=Convert.ToString(oZap[0,i]);
                                    
sValues+=Convert.ToString(oZap[1,i]);
                             }
                             else
                             {
                                    
sCategories+=Convert.ToString(oZap[0,i])+     ;//в конец добавляется табуляция
                                    
sValues+=Convert.ToString(oZap[1,i])+  ;//в конец добавляется табуляция
                            
}
                      }
               }
               
// Функция, выдающая одну круговую диаграмму 3D (1 ряд значений). Перегрузка 1 из 2. String.
               
public static Byte[] o1PieExploded3D1s(Int32 iX,Int32 iY,String sChartCaption,String sCategories1,String sValues1)
               {
                     
//var
                     
OWC11.ChartSpaceClass oChartSpace=new OWC11.ChartSpaceClass();
                     
Byte[] oImg;
                     
//end var
                      //активизация заголовка диаграммы
                     
oChartSpace.HasChartSpaceTitle=true;
                     
//создание заголовка
                     
oChartSpace.ChartSpaceTitle.Caption=sChartCaption;
                     
//создание первой диаграммы, нумерация с нуля
                     
oChartSpace.Charts.Add(0);
                     
//создание первого ряда значений, нумерация с нуля
                     
oChartSpace.Charts[0].SeriesCollection.Add(0);
                     
//заполнение ряда категорий
                     
oChartSpace.Charts[0].SeriesCollection[0].SetData(OWC11.ChartDimensionsEnum.chDimCategories,iDataLiteral,sCategories1);
                     
//заполнение ряда значений
                     
oChartSpace



Похожие статьи:
- Как запретить пользователю сохранять картинки?
- Передача и обработка данных средствами SSI
- Режем баннеры и popupы на бесплатных хостингах
- Меняемся баннерами и ссылками
- Сайт от идеи до реализации
- Сложные графики и диаграммы в ASP.NET. Часть четвёртая – ChartSpace.
- Пример создания многоязыкового приложения (XML)
- Проверка запроса – предотвращение атак скриптов
- Обработка ошибок в ASP.NET приложении.
- Основы создания серверных элементов управления. События.
- Меняем URL’ы на лету
- Средства безопасности ASP.NET. Аутентификация
- Как работают Web сервисы ASP.NET


Оглавление | Обсудить на форуме | Главная страница сайта | Карта сайта |

Контакты
Редакция:
[0.002]