Опубликован: 05.08.2010 | Уровень: специалист | Доступ: платный
Самостоятельная работа 5:

Просмотр данных OLE DB средствами ADO.NET

Упражнение 6. Вычисляемые столбцы объектов DataTable

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

SELECT EmployeeID, LastName + ', ' + FirstName AS FullName FROM Employees

формирует в кэше из таблицы Employees два столбца, первый из которых представляет столбец EmployeeID исходной таблицы, а второй - объединение данные двух исходных столбцов под псевдонимом FullName.

Команда

SELECT ProductID, ProductName, UnitPrice + UnitPrice * ? AS (Total Price)
    FROM Products

к двум исходным столбцам из таблицы Products добавляет вычислимый столбец TotalPrice, в котором содержится отпускная цена товара с учетом процента ставки налога, причем процент налога передается в команду как параметр.

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

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


Вычислимые столбцы нужно добавлять к объекту таблицы до заполнения ее данными из поставщика. Отдельные столбцы представляются в объектной модели таблицы классом DataColumn. Новый объект DataColumn добавляется в таблицу методом Add() свойства-коллекции DataTable.Columns.

Добавляемый в таблицу объект столбца должен содержать имя столбца (свойство ColumnName ), тип данных (свойство DataType ) и выражение (свойство Expression ) при необходимости. Выражение используется для фильтрации строк, вычисления значений в столбцах на основании других столбцов или для создания агрегированного (объединенного) столбца. Эти данные передаются в конструктор при создании объекта столбца или сразу в одну из перегрузок метода Add() при добавлении в коллекцию столбцов таблицы.

Типы данных, которые могут быть значениями свойства DataColumn.DataType, ограничиваются следующим списком пространства имен System:

Boolean (bool) Decimal Int64 TimeSpan
Byte (byte) Double (double) SByte UInt16
Char (char) Int16 Single (float) UInt32
DateTime Int32 (int) String UInt64

Свойство DataColumn.DefaultValue показывает, какое значение имеет по умолчанию данный столбец. Если столбцу не присвоено никакого значения, а значение по умолчанию не определено, то столбец имеет значение System.DBNull. Поскольку типы данных реляционной таблицы БД и виртуальной таблицы объектной модели могут быть разными, рекомендуется явно привести тип столбца к нужному вычислимому типу. И это нужно сделать до загрузки объектной таблицы!!!

Таблица DataTable, помимо прочего, имеет три коллекции в качестве свойств только для чтения:

  • Columns - содержит объекты столбцов вместе с их именами и типом
  • Rows - содержит фактические данные, упакованные в объектах строк
  • Constraints - содержит экземпляры классов ForeignKeyConstraint или UniqueConstraint, задающих свойства в отношении ключевых или уникальных значений полей

После добавления вычислимого столбца в коллекцию Columns объекта таблицы к нему можно обращаться в Columns по имени или порядковому номеру. Для иллюстрации сказанного выполните данное упражнение в следующем порядке:

  • Добавьте к решению проект оконного приложения с именем WinForms6 и назначьте его стартовым
  • Настройте пользовательский интерфейс в соответствии с таблицей
Компонент Свойство Значение
Form Text Упражнение 6
  MaximizeBox False
DataGridView (Name) dataGridView
  Dock Fill
  AutoSizeColumnsMode Fill
  • Заполните файл Form1.cs проекта WinForms6 следующим образом
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
    
// Дополнительные пространства имен
using System.Data.OleDb;
using System.Data.Common;
using System.Collections;
    
namespace WinForms6
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
    
            LoadProducts();
        }
    
        // Строка соединения к БД с абсолютным путем, определяемым сборкой
        String ConnectionString()
        {
            // Используем построитель строки подключения 
            OleDbConnectionStringBuilder objConnectionStringBuilder =
                new OleDbConnectionStringBuilder();
            objConnectionStringBuilder.Provider = "Microsoft.Jet.OLEDB.4.0";
            objConnectionStringBuilder.DataSource =
                Application.StartupPath.ToString() + @"\Data\Northwind.mdb";
    
            return objConnectionStringBuilder.ToString();
        }
    
        void LoadProducts()
        {
            // Формируем поставщик 
            OleDbCommand selectCommand = new OleDbCommand();
            selectCommand.CommandText = 
                "SELECT ProductID, ProductName, UnitPrice AS Price FROM Products";
            selectCommand.Connection = new OleDbConnection(ConnectionString());
            selectCommand.CommandType = CommandType.Text;
            OleDbDataAdapter adapter = new OleDbDataAdapter(selectCommand);
            
            // Создаем объект таблицы
            DataTable tableProducts = new DataTable();  
          
            // Задаем тип столбца, подлежащего заполнению данными из БД
            // (ДО ЕГО ЗАПОЛНЕНИЯ!!!)
            tableProducts.Columns.Add("Price");
            tableProducts.Columns["Price"].DataType = typeof(System.Decimal);
    
            // Добавляем и настраиваем вычислимый столбец для величины наценки
            tableProducts.Columns.Add("Margin", typeof(System.Decimal));
            tableProducts.Columns[1].Expression = "Price * 0.086";
    
            // Добавляем  и настраиваем вычислимый столбец для потребительской цены
            DataColumn totalPrice = new DataColumn("Total Price");
            totalPrice.DataType = System.Type.GetType("System.Decimal");
            totalPrice.Expression = "Price + Margin";
            tableProducts.Columns.Add(totalPrice);
            
            // Заполняем таблицу
            adapter.Fill(tableProducts);
    
            // Связываем таблицу с элементом отображения
            dataGridView.DataSource = tableProducts;
    
            Object result = tableProducts.Compute("Sum(Margin)", null);
            MessageBox.Show(String.Format("Суммарная наценка на товар\n"
                + "(по курсу 30 рублей за доллар): {0:C}",// Спецификатор денежного формата
                Convert.ToDecimal(result) * 30.0m));
    
            result = tableProducts.Compute("Count(Price)", "Price < 10");
            MessageBox.Show(String.Format("Количество товара с ценой меньше 10$: {0} шт.", result));
        }
    }
}
  • Запустите приложение - результат будет таким


Алексей Бабушкин
Алексей Бабушкин

При выполнении в лабораторной работе упражнения №1 , а именно при выполнении нижеследующего кода:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using Microsoft.Xna.Framework.Graphics;

   

namespace Application1

{

    public partial class MainForm : Form

    {

        // Объявим поле графического устройства для видимости в методах

        GraphicsDevice device;

   

        public MainForm()

        {

            InitializeComponent();

   

            // Подпишемся на событие Load формы

            this.Load += new EventHandler(MainForm_Load);

   

            // Попишемся на событие FormClosed формы

            this.FormClosed += new FormClosedEventHandler(MainForm_FormClosed);

        }

   

        void MainForm_FormClosed(object sender, FormClosedEventArgs e)

        {

            //  Удаляем (освобождаем) устройство

            device.Dispose();

            // На всякий случай присваиваем ссылке на устройство значение null

            device = null;       

        }

   

        void MainForm_Load(object sender, EventArgs e)

        {

            // Создаем объект представления для настройки графического устройства

            PresentationParameters presentParams = new PresentationParameters();

            // Настраиваем объект представления через его свойства

            presentParams.IsFullScreen = false; // Включаем оконный режим

            presentParams.BackBufferCount = 1;  // Включаем задний буфер

                                                // для двойной буферизации

            // Переключение переднего и заднего буферов

            // должно осуществляться с максимальной эффективностью

            presentParams.SwapEffect = SwapEffect.Discard;

            // Устанавливаем размеры заднего буфера по клиентской области окна формы

            presentParams.BackBufferWidth = this.ClientSize.Width;

            presentParams.BackBufferHeight = this.ClientSize.Height;

   

            // Создадим графическое устройство с заданными настройками

            device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware,

                this.Handle, presentParams);

        }

   

        protected override void OnPaint(PaintEventArgs e)

        {

            device.Clear(Microsoft.Xna.Framework.Graphics.Color.CornflowerBlue);

   

            base.OnPaint(e);

        }

    }

}

Выбрасывается исключение:

Невозможно загрузить файл или сборку "Microsoft.Xna.Framework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d" или один из зависимых от них компонентов. Не удается найти указанный файл.

Делаю все пунктуально. В чем может быть проблема?

Иван Циферблат
Иван Циферблат
Россия, Таганрог, 36, 2000