Опубликован: 09.09.2008 | Уровень: специалист | Доступ: платный | ВУЗ: Российская международная академия туризма
Лекция 15:

Связанные таблицы

< Лекция 14 || Лекция 15 || Лекция 16 >
Аннотация: В лекции рассмотрен пример использования связей между таблицами в реляционных хранилищах данных (создание и удаление связей). Пример также содержит описание функции оценки скорости выполнения запросов в связанных таблицах

Задача темы: изучить методику и получить навыки использования связей между таблицами в реляционных хранилищах данных

Разработка: Приложение "DataRelation" для оценки скорости выполнения запросов в связанных таблицах

Состав выполняемых функций:

  • Файловые операции: автоматическое открытие и загрузка данных из двух файлов
  • Алгоритмы: выборка данных из одного файла и добавление их в другой; оценка скорости выполнения запроса
  • Информационно-справочные: О программе

Наращивание функциональности не предусматривается.

Защита данных – нет.

В качестве входных данных используется XMLфайл Mersedes.xml с записями о периодах проведения регламентных работ и структурой, состоящей из полей: <Деталь>; <Цена>; <Фирма>; <Дата>; <Группа>; <О_ фирме>; <Услуга>; <Об _услуге>; <Пробег>; <ID> (фрагмент файла показан на рис.14.1).

Выходные данные программы:

  • XML – файл test_norm.xml с выборкой записей из файла Mersedes.xml о фактическом пробеге в момент проведения регламентных работ и структурой, состоящей из полей: <Деталь>; <Норма пробега>; <Фактический пробег>; <ID>. Выходной файл содержит несколько записей с заполненными полями, значение фактического пробега в поле <Фактический пробег> равно 0 – это поле будет заполнено в результате выполнения запроса. Полем связи таблиц является поле <Деталь>;
  • графическое отображение результатов результата выполнения запроса в DataGrid файла test_norm.xml и скорости выполнения запроса в текстовых полях формы для SmartDevice.

Рис. 14.1.

Шаг 1. Организапция дискового пространства

В каталоге \bin\debug размещаем оба файла – Mersedes.xml и test_norm.xml

Шаг 2. Организация графического интерфейса


Рис. 14.2.

Одна форма с кнопкой "Обновить связь", элементом DataGrid для вывода данных файла test_norm.xml, двумя надписями "Т обособленных таблиц" и "Т связанных таблиц", двумя полями для вывода результатов запроса к связанным таблицам и для вывода выборки из данных Mersedes.xml по ключу таблицы test_norm.xml. Примерный дизайн показан на рис.14.2

Из не видимых элементов – главное меню с опцией "О программе".

Шаг 3. Добавляем библиотеки

using System;
using System.Drawing;
using System.Collections;
using System.Windows.Forms;
using System.Data;
//добавляем 
using System.IO;
using System.Xml;
using System.Runtime;

Шаг 4. Определяем переменные в public class Form1 : System.Windows.Forms.Form

// организуем доступ (public static) из других классов (необязательно)
public static string file_name=@"\Mersedes.xml"; // пробег деталей
public static string file_norm=@"\test_norm.xml"; // нормы пробега
// глобальный датасет - объекты, содержащие ссылки на таблицы 
public static DataSet dataSetApp, dataSet, dataSet1; 
//глобальный дататейбл - таблицы
public static DataTable dataTableApp, dataTable, dataTable1 ;

Шаг 5. Дополняем процедуру загрузки формы public Form1()

{ // Required for Windows Form Designer support
InitializeComponent();
//создаем один объект для 2-х таблиц, иначе связь невозможна
dataSetApp=new DataSet();	
dataTableApp=dataSetApp.Tables.Add("Нормы");//1-я таблица в dataSetApp
// добавляем столбцы
dataTableApp.Columns.Add("Деталь",System.Type.GetType("System.String"));
dataTableApp.Columns.Add("Норма",System.Type.GetType("System.String"));
dataTableApp.Columns.Add("Факт",System.Type.GetType("System.String"));
dataTableApp.Columns.Add("ID",System.Type.GetType("System.Int64"));
// вторая таблица в dataSetApp			
dataTable1=dataSetApp.Tables.Add("Пробег замененных частей");	
// добавляем столбцы
dataTable1.Columns.Add("Деталь", 
System.Type.GetType("System.String")).MaxLength=100;
dataTable1.Columns.Add("Пробег", 
System.Type.GetType("System.String")).MaxLength=10;
dataTable1.Columns.Add("Дата", 
System.Type.GetType("System.String")).MaxLength=10;
// пытаемся прочитать файл
FileStream fin;		
try {
fin=new FileStream(file_norm,FileMode.Open);
fin.Close();
// Считываем значения из файла
XmlTextReader xml_in=new XmlTextReader(file_norm); 
dataSetApp.ReadXml(@xml_in);
xml_in.Close();
	}
catch(IOException exc) {
MessageBox.Show("Нет файла с нормами пробега \n"+file_norm,
"Ошибка открытия файла");
return;}
// программируем стиль грида, сортируем и привязываем данные файла норм
this.dataGrid1.TableStyles.Clear();
DataGridTableStyle tsApp= new DataGridTableStyle();
tsApp.MappingName="Нормы";
DataGridTextBoxColumn csApp=new DataGridTextBoxColumn();
csApp.Width=104;
csApp.MappingName="Деталь";
csApp.HeaderText="Деталь";
tsApp.GridColumnStyles.Add(csApp);

csApp = new DataGridTextBoxColumn();
csApp.Width=44;
csApp.MappingName="Норма";
csApp.HeaderText="Норма";
tsApp.GridColumnStyles.Add(csApp);
			
csApp = new DataGridTextBoxColumn();
csApp.Width=54;
csApp.MappingName="Факт";
csApp.HeaderText="Остаток";
tsApp.GridColumnStyles.Add(csApp);

csApp = new DataGridTextBoxColumn();
csApp.Width=50;
csApp.MappingName="ID";
csApp.HeaderText="ID";
tsApp.GridColumnStyles.Add(csApp);
				
this.dataGrid1.TableStyles.Add(tsApp);
DataView sortedView=new DataView(dataTableApp);
sortedView.Sort="Норма, Деталь";//  сортировка	
dataGrid1.DataSource=sortedView;// привязываем
}

Шаг 6. Создаем процедуру инициации запроса

Для кнопки "Обновить данные" пишем:

private void button1_Click(object sender, System.EventArgs e) {
FileStream fin;		
try {
fin=new FileStream(file_name,FileMode.Open);
fin.Close();
	}
catch(IOException exc) {
MessageBox.Show ("Невозможно открыть файл \n"+file_name,"Ошибка");
return;}
// Считываем значения из файла
XmlTextReader xml_in=new XmlTextReader(file_name); 
dataSet=new DataSet();
//Грузим данные из таблицы DataTable 
dataTable=dataSet.Tables.Add("Моя_Гну");
dataTable.Columns.Add("Деталь",System.Type.GetType("System.String"));
dataTable.Columns.Add("Цена",System.Type.GetType("System.String"));
dataTable.Columns.Add("Фирма",System.Type.GetType("System.String"));
dataTable.Columns.Add("Дата",System.Type.GetType("System.String"));
dataTable.Columns.Add("Группа",System.Type.GetType("System.String"));
dataTable.Columns.Add("О фирме",System.Type.GetType("System.String"));
dataTable.Columns.Add("Услуга",System.Type.GetType("System.String"));
dataTable.Columns.Add("Об услуге",System.Type.GetType("System.String"));
dataTable.Columns.Add("Пробег",System.Type.GetType("System.String"));
dataTable.Columns.Add("ID",System.Type.GetType("System.Int64"));
dataSet.ReadXml(@xml_in);
xml_in.Close();
// добавляем первую строку для шаблона
int my_test=0;
int my_maxpath=0;
int my_maxpath_up=0;
int my_maxpath_down=0;
string my_date="err";
string my_path="err";
string my_fuel, my_service;
foreach (DataRow row0 in dataTable.Rows) {
//вычисляем максимальный пробег	
my_maxpath_up=int.Parse(row0["Пробег"].ToString());			
if (my_maxpath<=my_maxpath_up)
my_maxpath=my_maxpath_up;
	}
my_maxpath_up=0;// обнуляем для выборки в группе
foreach (DataRow row in dataTable.Rows) {//cicle
my_fuel=(row["Деталь"].ToString());
// фильтруем с сортировкой
DataRow[] my_rows=dataTable.Select("Деталь='"+my_fuel+"'");	
foreach (DataRow row2 in my_rows ){
// вычисляем максимальный пробег детали
my_maxpath_up=int.Parse(row2["Пробег"].ToString());				
if (my_maxpath_down<=my_maxpath_up) {
my_maxpath_down=my_maxpath_up;
my_path=(my_maxpath-my_maxpath_down).ToString();
my_date=(row2["Дата"].ToString());
}
		}
my_maxpath_up=0;// обнуляем для выборки в группе
my_maxpath_down=0;// обнуляем для выборки в группе
my_test=0;
// проверяем группу в новой таблице по самому большому ID
foreach (DataRow row1 in dataTable1.Rows){
my_service=(row1["Деталь"].ToString());
if (my_fuel==my_service)
my_test=1;
		}
if (my_test==0){
object[] a1={my_fuel,my_path,my_date};
dataTable1.Rows.Add(a1);
		}
	}
/* устанавливаем связь между таблицами dataTableApp и dataTable1:
Объект главной таблицы - имя связи - поле связи в главной - поле 
связи в связанной таблице. Главная таблица та - в которой больше 
записей, а не наоборот, в противном случае генерируется исключение, 
что не хватает записей
*/
DataColumn[]{dataTableApp.Columns["Деталь"]};// в таблице "Нормы"
DataColumn[]{dataTable1.Columns["Деталь"]};//"Пробег замененных частей"
// тестируем варианты 
DateTime time_start;
DateTime time_finish;
if (MessageBox.Show("Выбираем данные из обособленных (Да) 
или связанных (Нет)таблиц?", "Тестируем 
варианты", MessageBoxButtons.YesNo, 
	MessageBoxIcon.Question,MessageBoxDefaultButton.Button2) = 
=  DialogResult.Yes) {// выборка по ключу
// считываем значения из таблицы норм
time_start=DateTime.Now;
foreach (DataRow row0 in dataTableApp.Rows) {
my_fuel=(row0["Деталь"].ToString());
my_maxpath=int.Parse(row0["Норма"].ToString());
foreach (DataRow row1 in dataTable1.Rows) {
my_service=(row1["Деталь"].ToString());
//вычисляем максимальный пробег
my_maxpath_up=int.Parse(row1["Пробег"].ToString());			
if (my_fuel==my_service)
my_maxpath=my_maxpath-my_maxpath_up;
			}
if (my_maxpath>=int.Parse(row0["Норма"].ToString()))
row0[2]="Заменить";
else
row0[2]=my_maxpath.ToString();	
		}
time_finish=DateTime.Now;
this.textBox1.Text=(time_finish-time_start).ToString();
	}
else{ // вариант запроса к  связанным таблицам
time_start=DateTime.Now;
dataSetApp.Relations.Add("Set_My_Relation", 
dataTable1.Columns["Деталь"], dataTableApp.Columns["Деталь"], true);
for (int i=0; i<dataTable1.Rows.Count; i++) {
//вычисляем пробег
my_maxpath_up=int.Parse(dataTable1.Rows[i]["Пробег"].ToString());
// считываем значения из таблицы норм
foreach (DataRow row0 
in dataTable1.Rows[i].GetChildRows("Set_My_Relation")) {
my_fuel=(row0["Деталь"].ToString());
my_maxpath=int.Parse(row0["Норма"].ToString());
my_maxpath=my_maxpath-my_maxpath_up;
if (my_maxpath>=int.Parse(row0["Норма"].ToString()))
row0[2]="Заменить";
else
row0[2]=my_maxpath.ToString();	
			}
		}
dataSetApp.Relations.Remove("Set_My_Relation");// разрываем связь
time_finish=DateTime.Now;
this.textBox2.Text=(time_finish-time_start).ToString();	
	}
time_finish=DateTime.Now;
MessageBox.Show("Загружены данные из файла \n"+file_name, "Готово");
}
14.1.

Шаг 7. Создаем процедуру просмотра строк DataGrid

private void dataGrid1_Click(object sender, System.EventArgs e) {
int N_row=dataGrid1.CurrentCell.RowNumber;
MessageBox.Show(// вывод значения ячейки
	dataGrid1[N_row,0].ToString()+"\n"+
	dataGrid1[N_row,1].ToString()+"\n"+
	dataGrid1[N_row,2].ToString(),dataGrid1[N_row,3].ToString());
}

Шаг 8. Создаем процедурку "О программе"

Для опции главного меню "О программе" пишем:

private void menuItem1_Click(object sender, System.EventArgs e) {
MessageBox.Show("Проблема:\n"+"Есть 2 XML-файла,из одного нужно 
выбрать данные и ввести их в другой.\n"+ "Решение:\n"+"Выборка 
перебором записей по условию в таблицу DataTable1,\n"+"связанной 
с таблицей DataTableApp в которой заполняются вычисляемые 
поля.\n"+"(C)Родигин Л.А., ноябрь 2006, платформа C# Visual 
Studio 2003", "О программе");		
}
< Лекция 14 || Лекция 15 || Лекция 16 >
jo jojo
jo jojo
Нидерланды
Ярославй Грива
Ярославй Грива
Россия, г. Санкт-Петербург