Bejelentkezés

E-mail: 
Jelszó: 
| Regisztráció | Jelszó? |
 



Menü

.Net világ havilap 2004. március - 4. oldal

Tárolt eljárás hívásának automatizálása

Egy  adatbázis-kezelő  alkalmazásban  gyakori  feladat,  hogy  meghívjuk  az  adatbázisunkban  lévő  tárolt  eljárásokat.  Egy  nagy  rendszerben  számtalan  tárolt  eljárás  lehet,  mindegyik  más  és  más  paraméterlistával  felvértezve.  Elérésükhöz  szinte  mindig  ugyanazokat  a  kódrészleteket  gépeljük  be  forráskódunkba:  létrehozunk  egy  SqlCommand  osztályt,  megadjuk  a  tárolt  eljárás  nevét,  felvesszük  a  szükséges  paramétereket,  melyeknek  értéket  is  adunk,  végül  pedig  futtatjuk  a  tárolt  eljárást.Nem  írhatunk  egy  olyan  általános  függvényt,  mely  képes  lenne  lekezelni  tetszőleges  nevű  és  paraméterlistájú  tárolt  eljárást.  Vagy  mégis?A  válasz:  igen!  Sőt!  Létrehozunk  egy  olyan  függvényt  -  CreateCommand  néven  -,  melynek  még  a  tárolt  eljárásnak  sem  a  nevét,  sem  a  paraméterlistáját  nem  kell  megadni.  A  függvényünk  deklarációja  a  következőképpen  néz  ki:  public  static  SqlCommand  CreateCommand(object[]  parameterValues)Egyetlen  bemenő  paraméterként  a  tárolt  eljárás  paramétereinek  adandó  értékeket  kell  tartalmaznia,  ezen  kívül  más  információra  nincs  szükség.  Eredményképpen  kapunk  egy  SqlCommand  osztályt,  melyben  a  kívánt  tárolt  eljárás  felparaméterezve,  meghívásra  készen,  használható  formában  rendelkezésre  áll.  Aki  nem  hiszi,  járjon  utána...

A  mellékelt  forráskód  kipróbálása  előtt  a  következő  néhány  előkészületi  lépést  kell  megtennünk:"    A  példához  az  MS  SQL  Northwind  példaadatbázisára  lesz  szükségünk;  ha  ez  nincs  telepítve,  akkor  tegyük  meg."  A  mellékelt  EmployeesListSP.sql  állományt  le  kell  futtatni  annak  érdekében,  hogy  az  EmployeesList  tárolt  eljárás  bekerüljön  a  Northwind  példaadatbázisba.  Ennek  legegyszerűbb  módja  a  mellékelt  Run.cmd  kötegelt  állomány  elindítása."    A  DataLayer.cs  forráskód  29.  sorában  lévő  connectionStr  változóban  lévő  kapcsolódási  sztringet  szükség  esetén  meg  kell  változtatni,  hogy  a  Northwind  adatbázis  programból  elérhető  legyen.A  megoldandó  problémaTegyünk  egy  kis  kitérőt  és  vizsgáljuk  meg,  mi  is  a  probléma  akkor,  ha  a  tárolt  eljárásokat  a  hagyományos  módon  érjük  el.  A  kitérőnk  idejére  is  maradjunk  meg  az  MS  SQL  Northwind  példaadatbázisának  tárolt  eljárásainál.Legyen  a  feladatunk  a  következő:  futtassuk  le  a  CustOrdersOrders  tárolt  eljárást  és  a  kapott  eredményt  az  egyszerűség  kedvéért  jelenítsük  meg  egy  DataGrid-ben.  Ehhez  a  következő  lépéseket  tennénk  a  hagyományos  esetben:            SqlConnection  connection  =  new  SqlConnection(                  connectionStr);            SqlCommand  c  =  new  SqlCommand();            c.CommandType  =  CommandType.StoredProcedure;            c.CommandText  =  "CustOrdersOrders";            SqlParameter  p  =  new  SqlParameter();            p.ParameterName  =  "@CustomerID";            p.Value  =  "WARTH";            c.Parameters.Add(p);            SqlDataAdapter  da  =  new  SqlDataAdapter();            da.SelectCommand  =  command;            DataTable  dt  =  new  DataTable();            connection.Open();            try            {                da.Fill(dt);            }            finally            {                connection.Close();            }            dataGrid1.DataSource  =  dt;A  fenti  kóddal  nincs  is  semmi  probléma,  a  célnak  tökéletesen  megfelel.  Ha  most  szükségünk  lenne  egy  másik  tárolt  eljárásra,  mondjuk  a  Sales  by  Year  nevűre,  akkor  fenti  kódot  lemásolva  csupán  a  tárolt  eljárás  nevét  kell  módosítani,  valamint  nem  egy,  hanem  két  paramétert  kellene  megadnunk,  mely  DateTime  típusú.  Belátható,  hogy  sok  tárolt  eljárás  hívása  esetén  feleslegesen  másolgatjuk  és  javítgatjuk  a  forráskódot.  Jó  lenne  egy  olyan  univerzális  függvény,  melyen  keresztül  bármelyik  nevű  és  bármilyen  paraméterlistával  rendelkező  tárolt  eljárás  elérhető  lenne.  És  hogy  igazán  könnyű  legyen  használni  ezt  a  függvényünket,  építsünk  bele  egy  olyan  logikát,  melynek  révén  se  a  tárolt  eljárásunk  nevét,  se  paraméterlistáját  ne  kelljen  megadni,  csupán  a  paraméterek  aktuális  értékét.MS  SQL  Northwind  példaadatbázis  tárolt  eljárásaiA  példaprogram  felépítéseMielőtt  nekilátnánk  a  gyakorlati  megvalósításnak,  tekintsük  át,  hogyan  is  építjük  fel  majdan  alkalmazásunkat.  Alapvető  problémánk  a  sok  tárolt  eljárás  egy  nagy  adatbázis-kezelő  rendszer  esetén.  Ebből  kifolyólag  nem  célszerű  egyetlen  forrásállományba  sűríteni  mindent.  Három  nagy  részre  bontjuk  tehát  a  feladatot.  Először  létrehozunk  egy  osztályt  DataLayer  névvel.  Ebben  kap  helyet  az  a  kód,  mely  a  közvetlen  adatbázis-eléréssel  foglalkozik.  Itt  valósítjuk  meg  az  SqlCommand  osztály  automatikus  generálását,  illetve  annak  futtatásakor  itt  kerül  feltöltésre  a  DataTable  is,  mely  az  eredményhalmazt  tárolja.  Második  részben  egy  LogicLayer  osztályt  hozunk  létre.  Ebben  olyan  kódot  helyezünk  el,  mely  a  DataLayer  által  szolgáltatott  adatot  feldolgozza,  megjelenítésre  kész  állapotba  helyezi.  Ide  célszerű  minden  olyan  program-logikát  helyezni,  mely  a  már  lekérdezett  adatokat  manipulálja.Végül  a  harmadik  rész  foglalkozik  az  adatok  fizikai  megjelenítésével.  Ez  kerül  a  Form1.cs  forráskódba.  Ide  már  nem  helyezünk  el  semmilyen  adatlekérdező  vagy  -manipuláló  kódot,  hiszen  ezekre  már  létezik  megfelelő  osztályunk,  itt  csak  az  adatok  megjelenítésével  kapcsolatos  kódnak  van  helye.A  CreateCommand  "mágus"Nézzük,  miként  is  varázsol  e  függvény  szinte  a  semmiből  egy  használható  SqlCommand  osztályt,  a  kívánt  tárolt  eljárásunk  meghívásához.Az  adatelérés  folyamata  a  következő:  a  Form1.cs-ben  meghívjuk  a  LogicLayer  osztály  egy  függvényét,  felkérve,  hogy  a  DataLayer-en  keresztül  adatot  olvasson  ki  azt  adatbázisból.  A  tárolt  eljárás  hívásához  át  kell  adnunk  ezeknek  a  függvényeknek,  hogy  aktuálisan  milyen  értékkel  történjen  a  tárolt  eljárás  meghívása.  E  két  dologból  már  minden  szükséges  információt  megadtunk  a  tárolt  eljárás  létrehozásához.Amikor  meghívjuk  ezt  a  függvényt,  annak  olyan  nevet  válasszunk,  mely  megegyezik  a  tárolt  eljárás  nevével.Hasonlóképpen  járjunk  el  a  paraméterekkel  is:  belső  függvényünk  minden  paraméterének  neve  egyezzen  a  tárolt  eljárás  paramétereinek  nevével.Ha  e  két  szabályt  betartjuk,  akkor  már  könnyedén  írhatunk  olyan  függvényt,  mely  meghatározza,  hogy  az  őt  meghívó  függvénynek  mi  volt  a  neve  és  paraméterlistája.  Ezekből  az  információkból  pedig  felépíthetjük  a  tárolt  eljárás  meghívásához  szükséges  SqlCommand-ot.Nézzük  ezt  egy  példán  keresztül:El  kell  érnünk  a  CustOrdersOrders  nevű  tárolt  eljárást,  melynek  egy  @CustomerID  paramétere  van.CREATE  PROCEDURE  CustOrdersOrders  @CustomerID  nchar(5)Ehhez  létrehozunk  a  LogicLayer  osztályban  egy  olyan  függvényt,  melynek  CustOrdersOrders  a  neve  és  egy  darab  CustomerID  nevű  paramétere  van.        public  static  DataTable  CustOrdersOrders(string              CustomerID)Programból  meghatározva,  hogy  a  hívó  függvény  milyen  nevű  és  paraméterlistájú,  már  könnyedén  megvalósítható  az  SqlCommand  létrehozása.  Nézzük:DataLayer.csCreateCommand  függvényA  CreateCommand  függvény  dolga  az,  hogy  létrehozza  a  szükséges  SqlCommand  osztályt  a  kívánt  tárolt  eljárás  meghívásához.  A  függvénynek  egyetlen  bemenő  paramétere  van,  mely  egy  object  típusú  tömb.  Ezen  keresztül  adhatjuk  meg  az  épp  aktuális  értékeket  a  tárolt  eljárás  paraméterei  számára.  Visszatérési  értékként  pedig  egy  SqlCommand  osztályt  kapunk.        public  static  SqlCommand  CreateCommand(object[]              parameterValues)        {Tudjuk  tehát,  hogy  annak  a  függvénynek  a  neve,  mely  meghívja  a  CreateCommand  függvényünket,  egyezik  a  tárolt  eljárás  nevével,  valamint  paraméterlistája  szintén  azonos.  Kérjünk  némi  információt  erről  a  hívó  függvényről.  Mivel  a  hívó  adatai  a  verembe  kerülnek,  így  onnan  ki  is  olvashatjuk  azt.  Ehhez  segítségül  a  StackTrace  osztály  újonnan  létrehozott  példánya  segít.  A  veremben  több  függvény  adata  is  megtalálható,  attól  függően,  hogy  hány  egymásba  ágyazott  hívás  történt.  Mivel  nekünk  most  az  előző  függvényre  van  szükségünk,  így  a  GetFrame(1)  hívással  ezt  kapjuk  meg  StackFrame  osztály  formájában.  Ennek  az  osztálynak  létezik  egy  GetMethod  nevű  függvénye,  amely  egy  MethodInfo  osztályt  ad  vissza  számunkra.  A  MethodInfo  osztályban  pedig  megtaláljuk  a  kívánt  információt:  ott  lesz  a  hívó  függvény  neve  és  paraméterlistája;  mindaz,  ami  a  tárolt  eljárás  hívásához  szükséges.            MethodInfo  method  =  (MethodInfo)new                  StackTrace().GetFrame(1).GetMethod();Most  már  nincs  más  dolgunk,  mint  felépíteni  a  szükséges  SqlCommand  osztályt.  A  létrehozott  SqlCommand  osztályban  a  tárolt  eljárás  nevét  annak  CommandText  property-jén  keresztül  adhatjuk  meg.  Ezt  a  MethodInfo  osztály  Name  property-jéből  nyerjük.  Ez  lesz  a  hívó  függvény  neve,  melynek  egyeznie  kell  a  meghívandó  tárolt  eljárás  nevével.            SqlCommand  c  =  new  SqlCommand();            c.CommandType  =  CommandType.StoredProcedure;            c.CommandText  =  method.Name;A  szükséges  paraméterek  létrehozásához  lekérdezzük  a  GetParameters  függvénnyel  a  hívó  függvény  paramétereit.  Az  így  kapott  tömbön  egy  foreach  ciklussal  megyünk  végig.  A  tömb  minden  eleme  egy-egy  ParameterInfo  osztály,  mely  az  adott  paramétert  írja  le.  Következő  lépésként  ellenőrizzük,  hogy  a  paraméternél  nem  lett-e  megadva  a  NonSqlParameter  attribútum  (ennek  okára  és  használatára  rögtön  visszatérünk).  Ha  ez  nincs  megadva,  akkor  létrehozunk  egy  paramétert  a  tárolt  eljárás  számára.  Ennek  nevét  a  ParameterInfo  osztály  Name  property-je  adja,  mely  elé  odatesszük  a  tárolt  eljárásokban  használatos  @  karaktert.  A  paraméternek  értéket  is  adunk,  melyet  a  mi  függvényünk  parameterValues  tömbjéből  veszünk.  A  ciklus  végére  az  SqlCommand  osztályunk  is  elkészül,  már  csak  vissza  kell  adnunk  azt  a  hívó  függvény  számára.            ParameterInfo[]  methodParameters  =                  method.GetParameters();            SqlParameter  p;            int  i  =  0;            foreach  (ParameterInfo  pi  in  methodParameters)            {                if  (!Attribute.IsDefined(pi,  new                      NonSqlParameter().GetType()))                {                      p  =  new  SqlParameter();                    p.ParameterName  =  "@"  +  pi.Name;                    p.Value  =  parameterValues[i];                    c.Parameters.Add(p);                    i++;                }                                        }            return  c;NonSqlParameter  attribútumA  NonSqlParameter  attribútum  használatának  megértéséhez  tegyünk  egy  kis  kitérőt.  A  CreateCommand  függvényünk  abból  az  adatból  dolgozik,  hogy  milyen  nevű  függvény  hívta  meg  azt,  milyen  paraméterlistával.  Ebből  következik  az,  hogy  amilyen  paramétere  a  hívó  függvénynek  van,  abból  tárolt  eljárás  paraméter  is  készült.  Viszont  ekkor  az  adatfeldolgozó  függvényünknek  nem  tudunk  más  paramétert  átadni,  csak  azt,  ami  a  tárolt  eljáráshoz  is  kell.  A  valós  programozási  feladatokhoz  ez  viszont  sok  esetben  nem  megfelelő.  Sokszor  előfordulhat  az  az  eset,  hogy  adatfeldolgozó  függvényünknek  nem  csak  a  meghívandó  tárolt  eljárás  paramétereit  kell  megadnunk,  hanem  más  egyéb  adatokat  is,  mely  a  kapott  eredmény  feldolgozásakor  szükséges.  Ebben  az  esetben  viszont  hibásan  működne  a  CreateCommand,  ha  az  minden  paraméterből,  válogatás  nélkül  tudna  tárolt  eljárás  paramétert  készíteni.Erre  a  problémára  ad  megoldást  egy  új  attribútum  létrehozása,  melyet  NonSqlParameter-nek  nevezünk  el.  Ezt  az  attribútumot  használva  a  függvényünk  egy-egy  paramétere  előtt,  rendelkezhetünk  arról,  hogy  ebből  ne  legyen  tárolt  eljárás  paraméter.  Az  attribútum  létezését  a  CreateCommand  függvényen  belül  ellenőrizzük,  és  ha  találunk  ilyet,  akkor  az  adott  paramétert  nem  használjuk  fel.  Az  attribútum  létrehozása  egyszerű,  a  lényeg  az,  hogy  az  Attribute  osztályból  származzon.  Mivel  ezt  az  attribútumot  egy-egy  paraméter  előtt  szeretnénk  alkalmazni,  így  erről  rendelkeznünk  kell  az  AttributeTargets  felsorolt  típus  Parameter  értékének  megadásával.    [AttributeUsage(AttributeTargets.Parameter)]    public  sealed  class  NonSqlParameter:  Attribute    {    }Így  nézne  ki  a  NonSqlParameter  attribútum  használata:        public  static  DataTable  CustOrdersOrders(              [NonSqlParameter]bool  OnlyOrderDate,  string              CustomerID)Látható,  hogy  az  OnlyOrderDate  paraméterünk  nem  tárolt  eljárás  paraméter,  annak  értéke  csupán  az  adatfeldolgozáshoz  kell  majd,  míg  a  CustomerID  értéke  a  tárolt  eljárásnak  átadandó  érték  lesz.CreateTable  függvényAdott  tehát  egy  SqlCommand  osztály,  futtatásra  készen.  Most  már  csak  arról  kell  gondoskodnunk,  hogy  ez  meg  is  történjen  és  az  eredményhalmazt  valamilyen  formában  más  metódusok  számára  is  érthető  módon  tároljuk.  Ehhez  a  sok  esetben  jól  használható  DataTable  osztályt  válasszuk.  Létrehozunk  egy  CreateTable  nevű  függvényt,  mely  paraméterként  a  már  adott  SqlCommand  osztályt  várja,  melyet  felhasználva  feltölt  egy  DataTable  osztályt  adatokkal.E  művelet  elvégzéséhez  az  SqlConnection  osztályt  segítségül  hívva  kapcsolatot  teremtünk  az  SQL  adatbázissal,  majd  egy  SqlDataAdapter  osztály  Fill  függvényét  meghívva  futtatjuk  és  feltöltjük  adatokkal  a  DataTable  osztályunkat,  melyet  már  csak  a  függvényünk  visszatérési  értékeként  kell  megadnunk.        public  static  DataTable  CreateTable(SqlCommand              command)        {            SqlConnection  connection  =  new  SqlConnection(                  connectionStr);            SqlDataAdapter  da  =  new  SqlDataAdapter();            da.SelectCommand  =  command;            da.SelectCommand.Connection  =  connection;            DataTable  dt  =  new  DataTable();            connection.Open();            try            {                da.Fill(dt);            }            finally            {                connection.Close();            }            return  dt;        }        }Ezzel  az  adateléréssel  kapcsolatos  függvényeink,  így  a  DataLayer  osztály  készen  is  van,  következhet  az  adatokat  feldolgozó  logika  létrehozása  a  LogicLayer  osztályban.LogicLayer.csAz  adatfeldolgozó  logika  -  jelen  példa  egyszerűségénél  fogva  -  sok  esetben  csak  szimplán  az  adatszolgáltató  függvények  meghívásából  áll.  Azonban  egy  valós  alkalmazás  esetén  ritka  az  az  eset,  hogy  egy  lekérdezés  után  az  adatok  rögtön  olyan  formában  állnak  rendelkezésre,  hogy  közvetlenül  megjeleníthetők.  Ezért  célszerű  az  adatfeldolgozó  logikát  külön  osztályban  elhelyezni,  még  akkor  is,  ha  ez  felesleges  lépésnek  tűnik.CustOrdersOrders  függvény  -  első  változatElső  függvényünk  feladata  a  CustOrdersOrders  nevű  tárolt  eljárás  meghívása  lesz.  Fontos  szabály,  hogy  függvényünk  neve  egyezzen  a  tárolt  eljárás  nevével,  hiszen  innen  veszi  majd  a  CreateCommand  függvény,  hogy  melyik  tárolt  eljárást  kell  a  készítendő  SqlCommand  osztályban  felhasználnia.  A  függvényünk  egyetlen  paramétere  szintén  egyezik  a  tárolt  eljárás  paraméterével,  mind  nevében,  mind  típusában.  E  feltételek  megléte  esetén  igen  egyszerű  a  dolgunk:  csupán  meghívjuk  a  CreateCommand  függvényt,  paraméterként  átadva  a  tárolt  eljárásnak  szánt  aktuális  értéket.  Az  így  kapott  SqlCommand  osztályt  rögtön  továbbítjuk  a  CreateTable  függvényünknek,  mely  futtatja  a  tárolt  eljárást  és  egy  adatokkal  feltöltött  DataTable  osztállyal  tér  vissza,  amit  mi  is  visszaadunk  a  hívó  metódusnak.        public  static  DataTable  CustOrdersOrders(string              CustomerID)        {            return  DataLayer.CreateTable(DataLayer.                CreateCommand(new  object[]{CustomerID}));        }CustOrdersOrders  függvény  -  második  változatA  második  példában  szintén  a  CustOrdersOrders  tárolt  eljárást  hívjuk  meg.  E  változatnál  láthatunk  példát  a  NonSqlParameter  attribútum  felhasználására.  A  függvény  első  paramétere  egy  olyan  adatot  tárol,  mely  a  lekérdezett  adatok  feldolgozásához  szükséges  és  nem  egy  tárolt  eljárás  paramétere.  Ezért  az  attribútummal  megjelöljük,  így  a  CreateCommand  nem  hoz  létre  ehhez  az  SqlCommand  osztályban  paramétert.  Függvényünk  második  paramétere  már  tárolt  eljárás  paraméter,  így  azt  az  előbbi  példához  hasonlóan  minden  jelölés  nélkül  írjuk  be.Adatfeldolgozó  logikánk  az  első  nem  tárolt  eljárás  paraméter  értékétől  függően  módosul.  Vagyis  ha  az  OnlyOrderDate  paraméter  igaz,  akkor  az  eredmény  DataTable-ben  csak  az  OrderDate  nevű  dátum  típusú  oszlopra  van  szükségünk,  így  a  másik  két  oszlop  törölhető.Meg  kell  említeni,  hogy  egy  valós  alkalmazás  esetén  e  megoldás  nem  lenne  a  legszebb.  Nyilvánvaló,  hogy  ilyen  helyzetben  a  tárolt  eljárást  kellene  úgy  megírni,  hogy  ha  nem  szükséges,  ne  is  adjon  vissza  feleslegesen  két  oszlopnyi  adatot.  Itt  most  csak  a  NonSqlParameter  attribútum  használatának  bemutatása  céljából  választottuk  e  példát.        public  static  DataTable  CustOrdersOrders(              [NonSqlParameter]bool  OnlyOrderDate,  string              CustomerID)        {            DataTable  dt  =  DataLayer.CreateTable(                DataLayer.CreateCommand(                new  object[]{CustomerID}));            if  (OnlyOrderDate)            {                dt.Columns.RemoveAt(3);                dt.Columns.RemoveAt(2);            }            return  dt;        }EmployeesList  függvényKészítettünk  egy  EmployeesList  nevű  tárolt  eljárást,  mely  nem  része  a  Nortwind  példaadatbázisnak.  Ezen  eljárás  két  különböző  típusú  paramétert  vár.  Amint  az  alábbi  példából  jól  látható,  ilyen  esetben  sem  bonyolódik  a  CreateCommand  és  CreateTable  függvényünk  használata,  melyekkel  ugyanolyan  egyszerűen  létrehozhatjuk  a  lekérdezést  és  annak  eredményét,  mint  az  első  CustOrdersOrders  függvény  esetében.A  CretateCommand  függvény  számára  átadandó  paraméterek  száma  és  típusa  tulajdonképpen  teljesen  az  adott  feladattól  függ,  és  semmilyen  korlátozással  nem  rendelkezik;  ha  éppen  30  paramétert  akarunk  átadni  egy  eljárásnak,  annak  sincs  semmi  akadálya.        public  static  DataTable  EmployeesList(DateTime              BirthDate,  string  Country)        {            return  DataLayer.CreateTable(                DataLayer.CreateCommand(new                      object[]{BirthDate,  Country}));        }EmployeesList  tárolt  eljárásAz  EmployeesList  tárolt  eljárásban  sem  végzünk  semmi  különlegeset:  egyszerűen  futtatunk  egy  select  lekérdezést  az  Employees  táblára,  megszűrve  annak  sorait  a  megadott  paraméterek  alapján.  Ne  feledjük,  hogy  az  EmployeesList  tárolt  eljárást  a  példaprogram  futtatása  előtt  a  Run.cmd  batch  állomány  futtatásával  hozzá  kell  adnunk  a  Northwind  példaadatbázishoz!CREATE  PROCEDURE    EmployeesList  (    @BirthDate  datetime,  @Country  nvarchar(15))ASSELECT  LastName  +  '  '  +  FirstName  AS  Name,  BirthDate,      CountryFROM      Employeeswhere    BirthDate>@BirthDate  and  Country=@CountryORDER  BY  BirthDateAz  adatfeldolgozó  logika  elkészülte  után  nem  marad  más  hátra,  mint  az  adatmegjelenítés,  melyet  a  Form1  végez.Form1.csAz  adatok  megjelenítéséhez  egy  DataGrid-et  használunk  a  példa  egyszerűségének  kedvéért.  A  példában  három  nyomógomb  segítségével  futtathatjuk  a  különböző  lekérdezéseket.  Mindegyik  esetben  csupán  annyi  a  teendőnk,  hogy  a  LogicLayer  megfelelő  függvényét  meghívjuk,  átadva  számára  a  szükséges  paramétert  és  a  visszakapott  DataTable  osztályt  megjelenítés  céljából  a  Form-on  lévő  DataGrid-hez  kössük.        private  void  button1_Click(object  sender,              System.EventArgs  e)        {            dataGrid1.DataSource  =  LogicLayer.                CustOrdersOrders("WARTH");        }A  második  példánál  egy  CheckBox  segítségével  választhatjuk  meg,  hogy  az  eredménytáblában  mindegyik  dátumoszlop  szerepeljen,  vagy  csak  az  általunk  választott  OrderDate.        private  void  button2_Click(object  sender,              System.EventArgs  e)        {            dataGrid1.DataSource  =  LogicLayer.                CustOrdersOrders(checkBox1.Checked,  "WARTH");        }A  harmadik  példa  is  egyszerű  függvényhívásból  áll,  két  tetszőlegesen  megválasztott  paraméterrel.        private  void  button3_Click(object  sender,              System.EventArgs  e)        {            dataGrid1.DataSource  =  LogicLayer.                EmployeesList(new  DateTime(1950,  1,  1),                  "USA");        }  A  mellékelt  példaprogram  a  kívánt  tárolt  eljárás  lefuttatása  utánPrethus  Gábor