Adatkezelés

Ez a fejezet a RecroGrid Framework adatbázis kezelésének alapvető beállításait mutatja be.

A RecroGrid Framework adatbázis kezelése, az Entity Framework által generált logikai modell, és a DbContext segítségével került megvalósításra. A konfigurációs beállításban megadható az alapértelmezett adatbázis connection és modell/context, de az egyes entitások külön modellben, vagy adatbázisban is szerepelhetnek, amit paraméterezéssel lehet megadni. A RecroGrid Framework teljesen kompatibilis a code-first típusú adatbázis kezelést használó alkalmazásokkal.

This topic contains the following sections:

List nézetű adatkezelés

Mezők definiálása

This section contains the following subsections:

Az entitásokat azok első használatuknál a RecroGrid Framework automatikusan legenerálja az Entity Framework logikai modell alapján. A mezők tulajdonságait a RecroGridRGProperty tárolja. Az itt beállított paraméterek határozzák meg, hogy a mező értéke milyen forrásból szerezhető be, hogyan kell megjeleníteni Lista és Form nézetben, milyen kapcsolatban áll más mezőkkel, entitásokkal. A tulajdonságokat az Adminisztrátor futásidőben tudja módosítani egy erre kialakított webes felületen.

Mezők definiálása logikai modell alapján

A ColName tartalmazza az entitás mezőjének nevét a logikai modell alapján. Adatbázis használatánál ez egyenértékű egy adott tábla egy oszlopával. A neveknek Alias is adható, ami kifejezések, duplikált mezők vagy szerencsétlenül elnevezett mezők esetén különösen hasznos. A felhasználók számára a ColTitle tulajdonság jelenik meg, amit javasolt RecroDict szótárban kezelni, ez az Adminisztrátori funkciókban automatikusan legenerálható.

A megjelenítendő mezőket, illetve azok pozícióját és szélességét futásidőben a felületen lehet állítgatni, és felhasználónkét külön el lehet menteni, az Adminisztrátor pedig az alapértelmezést tudja beállítani. A Readable tulajdonság meghatározza, hogy a felhasználó megjelenítheti-e List nézetben a mezőt. Azokat a mezőket, amiket a megjelenítéstől függetlenül mindig be kell olvasni az adatbázisból, azokat az RGO_Forced opciós paraméterben kell jelezni. A RecroGrid teljes funkcionalitásának használatához az entitásokban a kulcs mezőket az IsKey tulajdonsággal kell ellátni.

  Security Note

A kulcs mezők beállítástól függetlenül mindig kiküldésre kerülnek, ezért olyan entitások esetén ahol a kulcs mező nem nyilvános adat (ez logikailag is hibás) létre kell hozni egy külön kulcs mezőt. Javasolt mindig egyoszlopos kulcs kialakítása, a többoszlopos kulcsok létrehozása kerülendő. Mivel a kulcsok a további műveletek egyik azonosítóját képezik, a kliensre küldés előtt a RecroGrid ezeket digitális aláírással látja el. Az egyes mezők nevének kiküldése szintén biztonsági kockázatot jelent, ezért a RecroGrid kliensoldalon egy automatikusan generált ClientName névvel azonosítja a mezőket. A felületeken megjelenő ColTitle tulajdonság hiánya esetén a RecroGrid azt a ColName tulajdonságból próbálja előállítani. A teljes mezőszintű és adatfüggő jogosultsági rendszerhez javasolt a RecroSec használata.

Many to One (*-1 vagy *-0..1) kapcsolat esetén a ColName-ben csak meg kell adni a logikai modell szerinti útvonalat, és a rendszer automatikusan összekapcsolja a táblákat a definiált kapcsolatok alapján. Megfelelő kapcsolatok esetén a mező lehet akár több entitás távolságra is. Ha a külső mező EntityBase tulajdonsága beállításra kerül, akkor öröklődnek az opciós beállítások a ColTitle és a ClientName tulajdonságok, így a Listákban az azonos mezők egyforma stílusban jelennek meg. Az aktuális mezőhöz definiált opciók az örökölteket felülírják. Az öröklés az RGO_DisableInheritance opciós paraméterrel letiltható.

  Caution

Opciók öröklése esetén, a eredeti mező dinamikus stílusainak megvalósítása nagyobb odafigyelést igényel, mivel egy másik entitáshoz kapcsolva a saját entitásában található mezők nem léteznek, azokat külön fel kell venni.

Lehetőség van One to Many (1-*) kapcsolatú mezők megadására is, amit a RecroGrid Framework automatikusan felismer, és egy vesszővel szeparált felsorolást ad vissza. Ennek megjelenítése kliens és szerveroldalon egyaránt testre szabható.

SQL
--ColName: műfajok meghatározása egy film listában
ESQL:(select value g.Name from {0}.Genre as g)

  Tip

A One to Many kapcsolatok automatikus használata csak kisebb rekordszám esetén javasolt, mert lényegesen csökkenhet a teljesítmény, és megnőhet az adatforgalom. Nagyobb rekordszám (vagy nagyobb forgalom) esetén javasolt az ilyen mezőket szerveroldalon külön feltölteni.

Ha a névben csak egy külső entitás neve (aminek a logikai modellben a kapcsolata definiált) szerepel, akkor az entitás összes oszlopa beolvasásra kerül. A mező nevének egy speciális RG_Self nevű adat is megadható, ami típusosan beolvassa az összes oszlopot, ami az aktuális entitásban (logikai modellben) megtalálható. Ezt a mezőt Entity típusúnak kell definiálni.

  Note

Az RG_Self mező az RGO_Forced opcióval ellátva azt eredményezi, hogy a beállításoktól függetlenül az entitás összes mezője mindig beolvasásra kerül. Ez hasznos lehet egy bonyolultabb szerveroldali funkcionalitáshoz, aminek szüksége van mindig (majdnem) minden adatra.

.NET Core verzió esetén az RG_Self nem elérhető.

A RecroGrid által automatikusan generált adatbázis lekérdezések
--ColName: Person.FirstName
--Employee entitásban hivatkozás Person entitás mezőre
SELECT Extent1.*, Extent2.FirstName FROM [Employee] AS [Extent1] INNER JOIN [Person] AS [Extent2] ON [Extent1].[BusinessEntityID] = [Extent2].[BusinessEntityID]

--ColName: Employee.LoginID
--Person entitásban hivatkozás Employee entitás mezőre
SELECT Extent1.*, Extent2.LoginID FROM [Person] AS [Extent1] LEFT OUTER JOIN [Employee] AS [Extent2] ON [Extent1].[BusinessEntityID] = [Extent2].[BusinessEntityID]

--ColName: RecroGrid_Property.RecroGrid_Entity.Name
--RecroGrid_Options entitásban hivatkozás RecroGrid_Entity mezőre
SELECT Extent1.*, Extent3.Name FROM [RecroGrid_Options] AS [Extent1] LEFT OUTER JOIN [RecroGrid_Property] AS [Extent2] ON [Extent1].[PropertyId] = [Extent2].[PropertyId]
        LEFT OUTER JOIN [RecroGrid_Entity] AS [Extent3] ON [Extent2].[EntityId] = [Extent3].[EntityId]

EF logikai modellben nem szereplő kapcsolatok definiálása

Az olyan külső mezők esetén, amik a logikai modell alapján közvetlenül nem elérhetőek, a kapcsolatot manuálisan kell felépíteni. Ennek megvalósítására két opciós beállítás áll rendelkezésre az RGO_InnerJoin és az RGO_OuterJoin. A opciók hatására az SQL INNER JOIN és LEFT OUTER JOIN lekérdezésnek megfelelő eredmények érhetők el, paraméterezésük megegyezik.

Az opcióban kifejezést a külső tábla nevétől kezdődően kell megadni, a feltételeknél NSQL formátum használandó. A külső táblának mindenképpen Alias-t kell adni, és a névben azzal együtt és NSQL: előtaggal kell hivatkozni. Az aktuális tábla nevénél a {0} jelölés használandó.

SQL Join
ColName: NSQL:personExt.FirstName
RGO_InnerJoin: Person personExt on {0}.BusinessEntityID = personExt.BusinessEntityID

ColName: NSQL:category.ProductCategoryID
RGO_OuterJoin: ProductCategory category on {0}.ProductSubcategory.ProductCategoryID = category.ProductCategoryID

RGF Core: ColName: NSQL:category.ProductCategoryID
RGO_OuterJoin: ProductCategory category on [{0}.ProductSubcategory].ProductCategoryID = category.ProductCategoryID

  Note

.NET Core verzió esetén NSQL előtagot kell használni, illetve többszintű kapcsolat esetén a táblaneveket szögletes zárójellel jelölni kell [{0}.T1.Tx] formában.

Entity/Native SQL - egyedi kifejezések

A mezők definiálásakor lehetőség van SQL kifejezések meghatározására is, amiket a RecroGrid beilleszt a adatbázis lekérdezésekbe. Ezeket ESQL: előtaggal kell jelölni, és ESQL szabványnak megfelelően kell megadni. Ezen mezőknek kötelező Alias-t megadni.

  Note

.NET Core verzió esetén az ESQL kifejezés nem elérhető, helyette natív SQL kifejezéseket kell megadni NSQL előtaggal.

SQL kifejezések a mezők definiálására
--Alias: FullName
--case when, concat kifejezések
ESQL:Concat(case when {0}.Suffix is null then '' else Concat({0}.Suffix, ' ') end,
        Concat(case when {0}.Title is null then '' else Concat({0}.Title, ' ') end,
        Concat(Concat({0}.FirstName, ' '),
        Concat(case when {0}.MiddleName is null then '' else Concat({0}.MiddleName, ' ') end,
        {0}.LastName))))

--Alias: Exp
ESQL:concat(concat(cast({0}.CreditCard.ExpMonth as System.String), '/'),
        cast({0}.CreditCard.ExpYear as System.String))

--Alias: OrderCount
--Subquery: count(*)
ESQL:max(select value Count(o.ProductID) from {0}.Order_Details as o)

--Alias: PhotoId
--Subquery: (many to one)
ESQL:max(select value p.ProductPhotoID from {0}.ProductProductPhoto as p
        where p.ProductID ={0}.ProductID and p.Primary=true)

--Alias: LastStatus
--Subquery (many to many)
ESQL:max(select value top(1) poh.Status from PurchaseOrderHeader as poh
        where poh.PurchaseOrderID={0}.PurchaseOrderID order by poh.OrderDate desc)

--Alias: two
--konstans érték
ESQL:(2)

--Alias: PreExp
--ESQL Canonical Function
ESQL:AddDays(Expiration, 6)

Az NSQL:EntityBase. előtag használatával az NSQL típusú mező örökölhető az EntityBase azonos Alias mezőjéből, így az NSQL kifejezést csak egyszer kell megadni. Ha az útvonal egynél több entitást tartalmaz, akkor az útvonalat is ki kell írni.

NSQL kifejezés öröklése másik entitásból
--Person entitás FullName alias mezőjének öröklése
NSQL:EntityBase.FullName

--OrderDetails-ben a CategoryName (két entitás távolság)
NSQL:EntityBase.Products.Categories.CategoryName

Adatbázisban tárolt képek

Lehetőség van (bár nem javasolt) adatbázisban binárisan tárolni a képeket, amit a RecroGrid egy szerviz segítségével aszinkron módon külön lekérdezésekben képes beolvasni. Ebben az esetben a ListType-ot Image-re, a FormType-ot pedig ImageInDB-re kell állítani. A kliensen megjelenő IMG tag forrása egy felparaméterezett szerviz hívásra fog mutatni, amit a RecroGrid lekezel. Ha a kép egy másik entitásban van, akkor a ColName-ben a külső entitás kulcsát (oszlop nevét) kell megadni NSQL hivatkozással, (mert a külön adatbázis lekérdezéshez arra van szükség) a kép mező nevét pedig az RGO_ImageTarget opciós beállításban. A RecroGrid a képeket az entitás verziójával is ellátja, az RGO_ImageVersion opciós paraméterben definiált mező értékével, vagy ha ilyen nincs, akkor a globális beállítás szerinti RowVersionName mező értékével.

Dinamikus (adatbázisban nem létező) adatok kezelése

A dinamikus mezőket az IsDynamic kapcsolóval kell megjelölni, és tetszőleges nevet lehet adni. Ezek a mezők nem kerülnek bele az adatbázis műveletekbe, értékük futásidőben szerveroldalon és kliensoldalon is megadható.

Ha FormType típusa RecroDict, akkor a mező értéke közvetlen RecroDict szótár elem is lehet, akár az entitás egy mezőjének értékével paraméterezve.

C#
//RecroDict hivatkozás ClientName mező értékét felhasználva
Scope.@rg-col-31

//RecroDict hivatkozás ClientName paraméter átadással
Scope.StringId,@rg-col-31

Szűrés, rendezés és lapozás

This section contains the following subsections:

Szűrés

Az SQL lekérdezés WHERE feltételeit több automatizmus is szabályozhatja. A különböző típusú szűrők AND kapcsolatban állnak, tehát minden szűrő egy újabb szűkítő feltétel, amit egy másik szűrő nem képes felülbírálni. Azonban lehetőség van az SQL lekérdezés vagy szűrés teljesen manuális létrehozására is.

  • Az első szintű szűrés a felületről kapott szűrő, amit a RecroGrid Framework a UserFilter tulajdonságba tölt be. Ezt a szűrőt a felhasználó szabadon állíthatja az erre kialakított webes felületen. Az Adminisztrátornak lehetősége van a felületen beállított szűrőt alapértelmezett szűrőnek elmenteni, ami az RGO_UserFilter opciós paraméterbe kerül.

  • Lehetőség van szerveroldalon futásidőben definiált szűrők megadására is, amit a FixFilter tulajdonságban lehet beállítani. Ezeket tipikusan a manuálisan állított környezetfüggő szűrők.

    C#
    //Only the data of the current user
    FixFilter.Add(this, RGFilter.LogicalOperatorEnum.And, "UserId", RGFilter.SQLOperatorEnum.Equal, RecroSec.GetCurrentUserId(rgContext.HttpContext));
    
    //A separate filter object for a parenthesized condition
    RGFilter user1 = new RGFilter();
    user1.Add(this, RGFilter.LogicalOperatorEnum.Or, "FromUserId", RGFilter.SQLOperatorEnum.Equal, RecroSec.GetCurrentUserId(rgContext.HttpContext));
    user1.AddAliasCol(this, RGFilter.LogicalOperatorEnum.Or, "ToUserID", RGFilter.SQLOperatorEnum.Equal, RecroSec.GetCurrentUserId(rgContext.HttpContext));
    FixFilter.Add(RGFilter.LogicalOperatorEnum.And, user1);
  • A RecroGrid futásidőben automatikusan létrehoz környezetfüggő szűröket, ilyen az egymásból nyíló listák esetén a Parent/Child kapcsolat, illetve választás esetén a kezdő szűrő feltétel.

  • Az entitáshoz a RGO_FixWhere opcióban definiálható további NSQL formátumú fix szűrő is.

    SQL
    {0}.Status='Valid'
    
    exists(select * from {0}.Users A where A.Status = 'Valid')
  • Végül a lapozási információk kerülnek a szűrőbe, illetve RecroSec használatánál esetleges jogosultsági szűrők.

Az NSQL típusú mezőknél (pl. subquery) előfordulhat, hogy a szűrés használatához a eredmény típusát is definiálni kell, amit az RGO_SystemType opciós beállításba kell beírni. Alapértelmezés szerint ha ListType=Numeric vagy FormType=DropDown,ListBox akkor Int64 egyébként String.

Mezőnként lehetőség van egyedi szűrő kifejezés megadására, ami képes beépülni, a felhasználó által a felületen megadható szűrő rendszerbe. Ilyen szűrő tipikusan egy One to Many kapcsolat, ahol egy subquery tartalmazza a szűrést. A feltételt NSQL formátumban kell megadni az RGO_FilterExpression opciós paraméterben.

SQL
--A ColName egy subquery-t tartalmaz, aminek az eredménye egy felsorolás
ESQL:(select value g.Name from {0}.Genre as g)
--Az RGO_FilterExpression egy feltételt tartalmaz, amiben a {1} helyére a felhasználó a szűrési felületen a ColName-ben meghatározott
--lekérdezés eredményéből tud majd választani. A rendszer a szűrésnek megfelelő (equal, in, not in ...) műveleteket automatikusan berakja.
exists(select g from {0}.GenreList as g where g.GenreId {1})
--A fenti szűréshez az GenreList mezőt kötelezőnek kell beállítani: RGO_Forced=true

Rendezés

Az adatbázis lekérdezést a felhasználó tetszés szerint akár több oszlop szerint rendezheti. A rendezést felhasználónként el lehet menteni. Az Adminisztrátor a rendezést alapértelmezésnek tudja menteni, ami az RGO_Sort opciós beállításba kerül.

Lapozás

List nézetben a RecroGrid az adatokat blokkokban olvassa be az adatbázisból, amit lapozásnak hívunk. Az RGO_ItemsPerPage opciós paraméterben megadható, hogy a felhasználónak egyszerre mennyi sor látszódjon, az RGO_Preload paraméterben pedig, hogy az adatbázis lekérdezés esetén mennyi rekord kerüljön beolvasásra. Alapértelmezés szerint az RGO_Preload kétszerese az RGO_ItemsPerPage-nek, ami azt jeleni, hogy minden második lapozás esetén kell az adatbázishoz fordulni. Az összes beolvasott (beállítások szerint) adat kiküldésre kerül a kliensnek, és ott tárolásra (cache) kerül, tehát előre lapozás után a visszafelé lapozás már nem jár adatbázis művelettel. Az RGO_Resizable opció beállításával a felhasználónak lehetősége van a Lista átméretezésére, aminek hatására az egyszerre megjelenő adatok mennyisége megváltozhat.

Szótár típusú mezők megjelenítése

A RecroGrid egyik legkényelmesebb funkciója a Szótár kezelés, ami paraméterek alapján automatizálni tudja List nézetben a megjelenítést és szűrést, Form dialógusokon pedig a felvitelt/módosítást. Szótárként kezelendő mezőnek azt nevezzük, ahol egy külső listából választással kerül tárolásra az elem azonosítója. A külső lista lehet egy adatbázis tábla, statikus felsorolás vagy bármilyen egyéb lista, ami kulcs/megnevezés formában leírható. Ezeknek a mezőknek a FormType típusát DropDown-ra kell állítani. A különböző használati módok az RGO_DictionaryItems opciós paraméterben lehet beállítani.

  Tip

Javasolt Entitás szinten megadni szótárakat, ami utána minden hivatkozásnál egységesen használható, nem kell külön mezőnként felvenni. Néhány tucatnál nagyobb elemszámú listát nem javasolt szótárként kezelni, mert az jelenősen ronthatja a teljesítményt. Ilyenkor javasolt külön adatbázis táblát használni, és List nézetben azzal összekötni, Form nézetben pedig külső listából választani.

This section contains the following subsections:

Statikus

A legegyszerűbb beállítás az RGO_DictionaryItems opcióban a statikus felsorolás. A felsorolást kapcsos zárójelek között kell megadni, a kulcsot az értéktől kettősponttal, az elemeket pontosvesszővel kell elválasztani. White-space karakterek levágásra kerülnek. Az érték lehet RecroDict szótár elem is <%%>Scope.StringId formátumban. Ha a kulcsban vagy a megnevezésben kettőspont vagy pontosvessző szerepel, akkor a RecroDict megoldást kell használni.

C#
{0:;1:Bikes;2:Components;3:Clothing;4:Accessories}

{M:Male;F:Female}

{ :; GET:GET; SET:SET }

{ H:<%%>Entity.Product.Class.H; M:<%%>Entity.Product.Class.M }

RecroDict

A statikus listák helyett lényegesen jobb megoldás a RecroDict használata. A RecroDict számos előnye közül ebben az esetben nagyon jól jön, hogy támogatja a többnyelvű megjelenítést, kliens és szerveroldalon is kódból függvényeken keresztül elérhető, így egyéb feladatokra is használható. Adatbázisban tárolja az adatokat, ami online szerkeszthető és saját gyorsítótárral rendelkezik. Az RGO_DictionaryItems opciós paraméterben meg kell adni a szótár Scope azonosítóját a <%%> előtaggal. A <%%>KK: előtag esetén pedig Kulcs/Megnevezés páros helyett, Kulcs/Kulcs párokat generál.

C#
<%%>Entity.Product.Style

<%%>KK:Entity.Product.Class

Adatfüggő NSQL

Az RGO_DictionaryItems-ben egy NSQL formátumú lekérdezést is lehet megadni, ami egy Kulcs/Megnevezés párosból álló listát ad vissza. A lekérdezést NSQL: előtaggal kell jelölni. A lekérdezés szűrhető az aktuális rekord mezőinek értékeit felhasználva. Az egyes mezőkre a @ClientName jelöléssel lehet hivatkozni.

SQL
NSQL:select e.PropertyId, e.ColName from RecroGrid_Property e where e.EntityId=@rg-col-31

Callback

Lehetőség van szerveroldalon megvalósított függvény dinamikus meghívására, amit a RGO_DictionaryItems paraméterben a Callback:functionName formátumban kell megadni. A függvény definíciója public static List<KeyValuePair<string, string="">> functionName(RGProperty, EntityObject, ObjectContext) kell hogy legyen. A függvényt először az aktuális RecroGrid-ben keresi, ha ott nem létezik, akkor aktuális RecroGrid entitás típusában, ha ott sem, akkor az EntityBase típusú RecroGrid-ben és végül az EntityBase-ben használt entitás típusában.

C#
//RGO_DictionaryItems: Callback:GetGenders
public static List<KeyValuePair<string, string>> GetGenders(RGDictionaryCallbackParam arg)
{
    List<KeyValuePair<string, string>> items = new List<KeyValuePair<string, string>>();
    items.Add(new KeyValuePair<string, string>("M", "Male"));
    items.Add(new KeyValuePair<string, string>("F", "Female"));
    return items;
}

EntityBase

Ha egy Entitás szótárként kezelhető, akkor javasolt annak az entitásnak beállítani az RGO_DictionaryItems opciós paramétert, így minden hivatkozás automatikusan és egységesen működik. Az Entitásra beállítható szótár a mezőknél alkalmazható beállításokon kívül egy egyszerűsített query formátum is megadható Id,Name[,Order] formában, ami egy SQL lekérdezést készít az Entitás-ra. A harmadik paraméter opcionális, ami a rendezést határozza meg.

See Also

Other Resources