Лого на 91. НЕГ „Проф. Константин Гълъбов“

Модул 4 · Урок 13

Езикът C# — преговор с допълнение

Ред от таблица срещу инстанция на клас и кой тип на C# отговаря на кой тип на SQL Server — подготовката, без която свързването с базата не тръгва.

Двата инструмента, двете компоненти

Съвременните ИС се изграждат с архитектура клиент–сървър. В Модул 3 работихме с MS Access — програма, която се опитва да съвмести и двете компоненти в едно. Това става с цената на компромиси: нито функциите за сървърната част достигат нивото, което се иска от професионалистите, нито тези за клиентската (макар при клиентската ограниченията да са по-малки).

Професионалният подход е всяка компонента да се изгради с инструмент, който ѝ дава всичко необходимо. За сървърната част това е MS SQL Server — с основите му вече се запознахме. За клиентската част се връщаме към стар познат: универсалния език C#, с който клиентската компонента става по-ефективна, по-надеждна и най-вече по-удобна за крайните потребители.

Ключово

SQL Server е инструментът за сървърната част, C# — за клиентската. Този урок подготвя срещата им: как един ред от таблица се превръща в обект и кой тип на кой отговаря.

Ред от таблица и инстанция на клас

Обектно-ориентираният подход структурира данните като инстанции на клас от обекти. Ако искаме да обработваме записите от таблицата Student на базата School, създаваме съответен клас:

public class Student
{   public int idStudent;              //уникален номер
    public string name, surname, family;   //име
    public string egn;                //ЕГН
    public DateTime birt_day;         //дата на раждане
    public string birt_place, district;    //място на раждане
    public string e_mail, mobile;     //ел. поща и телефон
    // методи
    ...
}

Инстанцията на такъв клас е естественият начин да представим данните от един ред на таблицата — при едно условие: сигнатурата на класа (редицата от типове на атрибутите) да съответства на сигнатурата на таблицата. Типовете в SQL Server са много повече и по-разнообразни — това е нормално, целта на сървъра е преди всичко съхраняване на данни. Но ако се абстрахираме от разнообразието на текстовите типове и ги заместим със string, структурни разлики няма.

Има обаче две разлики, които трябва да знаеш:

Таблица в SQL ServerКлас в C#
Подредбаредовете са съхранени заедно, в някакъв порядъквсяка инстанция съществува самостоятелно — за еквивалент трябва масив от инстанции или друга структура
Поведениена методите съответстват съхранените процедури, но те не са обвързани с конкретните редоведефиницията съдържа и данни, и методи за обработката им — капсулирани заедно

Бележка

Механизъм, който да свърже редовете на една таблица със съхранените процедури така, както капсулирането свързва данни и методи в един клас, просто няма. И това е естествено — двата инструмента имат различни роли.

Конзолно приложение или с графичен интерфейс

В средата MS Visual Studio с C# създаваме два основни вида приложения — конзолни и с графичен интерфейс. Когато става дума за комерсиален продукт — ИС, разработвана по заявка на клиент — почти задължително е тя да е с графичен интерфейс: крайните потребители са свикнали с него и очакват точно такова приложение.

Има смисъл обаче и от конзолни приложения за връзка със сървъра. Освен потребителите, които въвеждат и обновяват данни, важна е и позицията на администратора на базата — той се грижи за целостта, актуалността и предпазването на данните от загуби. Неговите нужди до голяма степен вече се покриват от SSMS, което също е с графичен интерфейс. Затова конзолно приложение за връзка с БД може да потрябва само при много необичайна обработка, каквато в SSMS не е предвидена — а това ще става рядко.

Бележка

В този курс примерите са конзолни по друга причина — браузърът не може да изпълни Windows Forms. Логиката зад една екранна форма обаче е същата: ще я четем и пишем като конзолна програма.

Съответствие на типовете

Числови типове

Съответствието между числовите типове на C# и тези на T-SQL е неблагоприятно — не всеки тип от едната страна има аналог от другата. Затова, ако в базата се съхраняват много големи числови стойности, изборът на тип в програмата иска особено внимание.

SQL ServerC#Забележка
bitняма аналогможе да се използва byte (или bool)
tinyintbyte[0, 255]
smallintshort[−32768, 32767]
intint[−2 147 483 648, 2 147 483 647]
bigintlongнай-широкият цял тип и от двете страни
decimal(p,s)decimalинтервалът на decimal е по-къс
moneyняма аналогможе да се използва double; за smallmoneyfloat
realfloatинтервалът на float е по-къс от този на real

Внимание

Типовете sbyte, ushort, uint и ulong нямат аналог в SQL Server. Обратното също важи — затова преди да избереш тип, погледни интервала от допустими стойности, а не само името.

Текстови типове

Класът string в C# съхранява текстове в 16-битово (2-байтово) представяне — Unicode/UTF-16. В таблиците на SQL Server са допустими както 2-байтовите nchar(n), nvarchar(n|MAX) и ntext, така и 1-байтовите char(n), varchar(n|MAX) и text. При четене от базата и при записване в нея може да се наложи преобразуване на типа.

  • binary(n) и varbinary — може и string, но е разточително след прекодирането с 2-байтова таблица; алтернатива са масиви от bool.
  • image — съхранява обекти със сложно вътрешно форматиране (изображения, звук, видео); съответният тип в C# е Bitmap.

Дата, час и специфични типове

C# предоставя специализирания клас DateTime. С него се четат стойностите на атрибути от типовете datetime, datetime2, smalldatetime, date и time — със съответните ограничения, а записването става в някой от първите три. Алтернативата е данните за дата и час да се превръщат в низове, но тогава губиш методите на DateTime.

SQL ServerВ C#
sql_variantинстанция на „глобалния“ клас object с последващо преобразуване до подходящ тип
uniqueidentifier16-елементен масив от byte (или 4-елементен от uint, или 2-елементен от ulong)
xmlниз със специфичен формат — спокойно се пази в string

Практикум

Задача 1

Припомни си важни моменти от програмирането на C#: как се стартира създаването на конзолно приложение и на приложение с графичен интерфейс, как се създава клас от обекти, как се създават и четат двоични (позаписни) файлове, как се създават екранни форми.

Задача 2

По образеца на класа Student създай класове от обекти, съответни на таблиците на базата от данни, която проектира в предишния раздел.

Въпроси

Кои типове на SQL Server най-трудно ще намерят подходящо представяне в C#? За тип на SQL Server, който липсва в C#, в кой тип да се преобразува — и винаги ли обратното преобразуване е възможно? Как започва преобразуването на стойност от един тип в друг в C#?

Какво трябва да запомниш

  • SQL Server изгражда сървърната компонента, C# — клиентската; Access съвместява двете с цената на компромиси.
  • Един ред от таблица се представя от инстанция на клас, стига сигнатурата на класа да съответства на сигнатурата на таблицата.
  • Таблицата е съвкупност от подредени редове — в C# ѝ съответства масив от инстанции, а не единичен обект.
  • Класът капсулира данни и методи заедно; в базата на методите съответстват съхранените процедури, но те не са обвързани с редовете.
  • Съответствието на числовите типове е непълно — проверявай интервала от допустими стойности, а не името на типа.
  • string е 2-байтов (UTF-16), а в базата има и 1-байтови текстови типове; за дата и час се ползва DateTime.