Verziókövetés szolgáltatásfejlesztésnél
2008-03-25T20:07:43+01:00
2008-03-27T13:29:11+01:00
2022-07-26T01:47:23+02:00
  • Ez most vettem észre. Nem csak Magyarországon, hanem egy csomó 'ámítógépes rendszernél megy ez így. Igaz, hogy ezt a megoldást jóval egyszerűbb kivitelezni, ellenben skálázni nem lehet, nem tudjuk bevonni Juliska nénit ugyan ebbe a munkába, ha bővítjük a céget, és sok lesz az adat. Ráadásul Marika néninek meg kellene magyarázni azt az eljárást, amivel az adott dossziéba módosítást lehet felvenni.

    Szaknyelven: rowlock + túl vastag kliens.
    Mutasd a teljes hozzászólást!
  • Lehet, hogy az nem UpdateMode, hanem ConflictMode. Nincs előttem a designer. Ez a legalsó kallanyú a panelen.
    Mutasd a teljes hozzászólást!
  • Az előbb említett konkurenciakezelés LINQ to SQL megvalósítása így néz ki (egy település nevét módosító operation contract):

    // A LINQ to SQL adatkontextus kezelese operation behavior, // kulon lehet szabalyozni, hogy csak olvashato, // vagy irhato kontextust kerunk = ezzel sem kell szorakozni a // megvalositas kodjaban [PartnersDataOperation(false)] // WCF MessageContract pattern, // aktualizalt generikus osztalyokkal megvalositva public SettlementCRUDMessage.UpdateNameData.UpdateDataResponse UpdateSettlementName(SettlementCRUDMessage.UpdateNameData.UpdateDataRequest request) { // elkezdem felepiteni a modositando LINQ2SQL entitast // a konkurenciaellenorzes modja: WhenChanged var settlement = new Settlement { UID = request.UID }; if (request.CurrentData != null) { // ha a kliens kuldott elozo nev verziot, akkor beirom settlement.Name = request.CurrentData.Name; } else { // ha nem, akkor lekerem. // lekereskor .Single() operator, igy egybol el fog bukni // a hibas vagy nem letezo UID // a kiveteleket a WCF pipeline dolgozza fel // a kivetel adataibol, a CurrentOperation-bol es az // aktualis Request uzenetekbol mindig elo tudjuk allitani a // megfelelo SOAP faultot, igy itt nem kell ezzel szorakozni settlement.Name = dc.Settlements .Where(c => c.UID == request.UID) .Select(c => c.Name) .Single(); } // az entitas UID es a Name ok, mehet az Attach dc.Settlements.Attach(settlement, false); // beallitom, hogy mire akarom megvaltoztatni settlement.Name = request.Data.Name; // mondok egy Submit-et. // ket eset - // 1: a kliens kuldte az elozo Name verziot, azt az Attach elott irtuk be // A az Update el fogja kuldeni az elozo verziot szepen, // kapunk egy kivetelt ha nem jo, // amit lehet kezelni szinten a pipelineben // 2: most kertuk le az aktualis verziot, // az Attach elott be is irtuk, // a kliens kuldott egy uj verziot, csak akkor megy Update, ha // ez a ketto kulonbozik dc.SubmitChanges(); // ertelem szeruen az UpdateMode: WhenChanged miatt itt csak // Settlement.Name-t modosito update parancs fog menni, // mas dologgal nem terheli a szervert a LINQ to SQL var response = new SettlementCRUDMessage.UpdateNameData.UpdateDataResponse(); // Ha a kliens ker aktualis verziot az adatokrol // akkor kuldunk neki a valaszban, had oruljon neki // Ennek akkor van ertelme igazabol, ha a szerver // kozmetikazza a mentett adatokat, itt nincs ilyen // de a minta megkivanja, es elfer ez a 3 sor. if (request.RequestForUpdated) { response.UpdatedData = new SettlementCRUDMessage.NameData { Name = settlement.Name }; } return response; }
    Mutasd a teljes hozzászólást!
  • Én jelen pillanatban ennek az egész mókának a WPF + LINQ to Objects -re kihegyezett verzióján dolgozom, az Astoria projekt hagyatékaiból kiindulva. Ha lekérsz módosítani egy entitáshalmazt, akkor az egy típusos dokumentum, kőbe van vésve, immutable az egész. A WPF az egyes elemek INotify* wrap-ével dolgozik, ahonnan minden változás eseményeken keresztül buborékozik előre egészen egy ChangeTracker command pattern megvalósítás felé. Itt készül log minden egyes változásról, legyen az egy tulajdonság vagy egy reláció megváltozása. A lényeg, hogy minden halmaz egy egységes dokumentum, azon változatatni senki sem tud, az UI felületen a változtató parancsok aggregációjának eredménye látszik. (A megvalósításból következik, hogy minden csiszem-cseszem művelet zokszó nélkül visszavonható a dokumentum lekérése pillanatáig.)

    A szerverre mentés keményen LINQ to Objects alapú, a logon futtatot kverikkel dönti el a kliens, hogy pontosan mit is kell elküldeni a szerverre, minden típusos halmaz dokumentumnak saját értelmezője van. A Sumbmit után egy-egy document changed lesz broadcastelve, ami alapján a felület egyből az aktuális állapotokat fogja tükrözni.

    Elsőre életképesnek tűnik a dolog, a LINQ rengeteget segít, ha nem lenne, eszembe nem jutott volna hasonló rendszer megvalósításán agyalni.

    A forgalmi adatok, munkafolyamatok leírói, státusz információk mind a WF runtime mögött ülnek. Az egész lekérdezhetőségéről egy saját persistence megoldás gondoskodik, bizonyos szerializációk nem bináris folyamba, hanem SQL táblákba történnek, így a Workflow megszólítása nélkül is lehet tudni, hogy éppen ki-kivel van.

    Az a lényeg, hogy úgy döntöttem, hogy olyan 3.5-ös rendszert rajzolok, amilyet csak lehet, aztán meglátjuk, hogy mi lesz a végén belőle.
    Mutasd a teljes hozzászólást!
  • itt egy példaprojekt, ennek a bemutatóelőadásán hallottam ezt a fajta megközelítést: Microsoft Corporation
    Mutasd a teljes hozzászólást!
  • Koszi a valaszokat!
    Szerintem bizonyos alkalmazasi teruleteken igen is van helye a record szintu lock-nak. Jelentosen egyszerusitheti a megvalositast es sok esetben elfogadhato, hogy hmm most valaki lock-olja, akkor ezt most nem tudom valtoztatni - vagy szolok/irok neki. A valo eletbol vett peldatoknal is latszik, hogy ez a modszer egyszerubb. Amikor visszament a dosszie mar nem kell rajta semmit sem ellenorizni mint a masik esetben hisz az mindig a up-to-date.
    Igaz persze, hogy nagy rendszereknel a masik megoldas az udvozitobb.

    Hogy oldanatok meg egeszen pontosan a ket modszert? Mik a bevalt technikak? WCF + LINQ to SQL hatterrel - es bar nem fontos de windows klienssel.

    A bonyolultabb eset nyilvan nagyobb reszletezest igenyel.
    Milyen automatikus megoldasokat tudunk kihasznalni?
    Tegyunk timestamp-et minden record-ba (mondjuk lastChanged) es az frissuljon ha a user valtoztat rajta maganal es submit-nal csak ez a datum dontson? Ez persze adatvesztessel jarhat (x lekeri, utana y is, x modosit A mezot, x visszakuld, y modosit B mezot, y visszakuld -> y record-ja lesz az ervenyes pedig kozben x modositotta A-t). Vagy jobb lenne mindig eltarolni es elkuldeni egy "submit"-nal hogy mi volt a record valtoztatas elott? Az alapjan mar kiszedhetnenk, hogy melyik mezovel foglalkozott es csak azt frissitenenk. Van erre automatizmus?

    Igy vagy mashogy? Mi az udvozito?

    Erdekes es szerteagazo a tema, irjatok! :)

    ---
    Hopp, csak most olvastam az utolso hozzaszolast - koszi simi.2
    Erdekes.
    Tudsz erre egy elo peldat mutatni? - emlitetted, hogy MS-nel is lattad.
    Ennel mar csak az lenne jobb ha ez inkabb a szerver oldalon zajlana le.
    Mutasd a teljes hozzászólást!
  • architektúrálice a következő megoldást találtam ki erre egyszer (és ez megint egy jokernek bizonyult, azóta mástól is láttam, nevezetesen a ms-től, úgyhogy talán nem rossz):

    kliensoldalon a szerverkommunikációt két modulba pakolod szét:

    1) szolgáltatás ágens: a szerverműveletek meghívásáért felelős

    2) adat ágens: a kliensoldalon tárolt entitásverziók adattartalmáért felelős (cache, invalidálás logika, hivatkozások feloldása, verzióütközés feloldásnál merge stratégiák, stb)


    mikor lekérdezel valami adatot a GetValami() hívással, olyankor a szolgáltatás ágenst szólítod meg, a visszaadott érték pedig megy az adat ágensbe, azaz a cache-be. ő matyizik vele, ideoda drótozgat (pl. eseménykezelőket), majd ezt a bekábelezett verziót kapja vissza a kliens, mint a művelet eredményét.

    mikor a cache-ben tárolt Valami entitás hivatkozik egy MásValami-re, ami még nincs lekérdezve, akkor ezeken a rádrótozásokon keresztül az adat ágens rájön, hogy frissíteni kell. tudja, hogy mit kell mondani a szolgáltatás ágensnek ezért, elküldi a szervernek az üzenetet, a válasz meg majd visszajön

    mikor valakiről, akit már a cache-ben tartunk, megtudjuk hogy új verziója van a szerveren, az adat ágens feladata, hogy a két verziót összefésülje (akár úgy, hogy valami felhasználói döntést vár, stb)


    így a mentés scriptje a következő tud lenni:

    1. user módosított valakit, adat ágens észreveszi hogy "dirty" lett

    2. user "mentés"-t nyom, szolgáltatás ágens küld egy StoreValami hívást

    3. szerver visszatér, hogy porbléma van, konkurrencia fennforgása áll fenn, csinálj valamit

    4. elkérjük az entitás új verzióját

    5. az adat ágens összedolgozza a nála levő "dirty" verziót a szerveren tárolttal

    6. az új verziót újra elküldjük a szervernek, aki boldogan elmenti azt


    (a változásdetektálás legtöbb helyen timestampinggal vagy szig mon növekvő verziószámozással megy)

    chikk megoldása annyiban különbözik, hogy nála a kliens diffgrammokat küld a szervernek ("módosítsd ezt-és-ezt a mezőt"), azaz a merge logika szerveroldalon valósul meg. néha az a jó megközelítés (pl. alapklasszifikációs törzsadattároló szolgáltatásoknál), néha ez (pl. mikor a változások összefésülése felhasználói beavatkozást igényel).
    Mutasd a teljes hozzászólást!
  • El kell képzelni, hogyan történne az egész számítógépek és hálózat nélkül.

    Egy másik alternítíva:
    Marika néni küld egy levelet a pestieknek, hogy küldjék már le legyen szíves az őt érdeklő aktákat. A pestiek kiszedegetik a dossziékat és helyére tesznek egy papírt: Marika néninek elküldtük Piripócsra. Marika néni végignyálazza az aktákat és javítja maga ha valami kell.
    Ha közben valaki más is alkérné ugyan ezeket az csak egy üzenetet kap: "Bocs, de Piripócson van!".

    Magyarországon ez biztosan így működne .
    Mutasd a teljes hozzászólást!
  • Ugyan úgy nem jó ötlet Marika néni kávézásához igazítani az adatmódosítást (lock), mint ahogy nem jó ötlet egy-egy adatbázissor verziójához kötni minden egyes entitás módosíthatóságát. Ez utóbbi csak egy kicsivel szerencsésebb, mint a teljes lock. Mért ne tudnám én megváltoztatni egy vevő e-mail címét, ha ő a webes felületen aközben módosítja az ICQ elérhetőségét, miközben én is szakértem az adatait? Vagy egy rendszerművelet, ami történetesen a törzsadatok közt végez módosítást, amit, mivel rendszerművelet, zokszó nélkül végre kellene tudni hajtani, csak azért bukjon el, mert valaki az adott adatbázissorban módosított valami olyan adatot, aminek a világon semmihez nincs semmi köze (megváltoztatta a haja színét, és ezt közölni kívánja egy online társkereső oldalon).

    A kliens-szolgáltatás forgatókönyvnél disconneted-ebb modell nem létezik (de szép szó), eszerint kell megvalósítani az adatmódosítást.

    El kell képzelni, hogyan történne az egész számítógépek és hálózat nélkül. Adatfeltöltö adjunktus Marika néni lekéri az áprilisban felvett új jómunkásembereink adatait levélben, ez egy üzenet. Egy levélben kapja a választ, ahol ott a lista, benne minden jómunkásember adata. Észre veszi, hogy a #23435-ös azonosítójú Kis Béla neve el van barmolva, Kiss Bélának kéne ott lenni. Fog egy papírt, ráírja, hogy "Kérem módosítsák már a #23435-ös számú jómunkásember nevét, mert Önök szerint az ott Kis Béla, szerintem meg Kiss Béla kéne, hogy legyen!". Ez az üzenet, megy fő Pestre levélben. Ott feldolgozzák Marika néni üzeneteit, megnézik, hogy valóban el van-e szabva Kiss Béla jómunkásember neve Kis Bélára. Ha igen, akkor kijavítják, megy a levél Marika néninek, hogy Ok, javítottuk. Marika néni szépen ráírja a listájára, hogy ez az adat már rendben van. Ha a Pestiek azt látják, hogy náluk közben már valaki kijavította, a #23435-ös már Kiss Béla, akkor megy a válasz Marika néninek, hogy sorry muter, nálunk a #23435-ös már Kiss Béla, nem kell aggódni, no para.

    Ennek a procedúrának semmi befolyása nem lesz Piroska néni munkájára, aki ugyan ezekkel az adatokkal dolgozva a jómunkásemberek lakcímét és egyéb elérhetőségét ellenőrzi.

    Teljesen ugyan ezt kell megvalósítasni levelek és papírok helyett SOAP üzenetekkel.
    Mutasd a teljes hozzászólást!
  • Eleve nem csípem az offline adatmodell-t, de lassan kénytelen leszek megbarátkozni vele.

    A legegyszerűbb megoldás, ha az update query-t kiegészíted egy kis feltétellel (ehhez nem kell semmi a szerver oldalon):
    UPDATE table1 SET mezo1 = @mezo1_new, mezo2 = @mezo2_new, ... WHERE ID = @ID AND mezo1 = @mezo1_old, mezo2 = @mezo2_old, ...
    Így ha idő közben megváltozott a rekord akkor nem lesz a feltételnek eredménye, az "effectedrows" = 0 -> szeva.
    VS is így csinálja, ha varázslóval pesszimista query-t kérsz (legalább is mikor utoljára néztem akkor ezt tette). Az _old értékeket lehet kötni valahogy a DataRow eredeti állapotához.
    (már ha ezek a fogalmak léteznek manapság*).

    Ennél szebb megoldás a timestamp mező, de ez egyrészt SQL Server specifikus, másrészt szerver oldali tervezést igényel.

    A lehető legrosszabb megoldás a direkt lock, hisz ekkor ha Julika néni elmegy kávézni, miközben megnyitotta módosításra a rekordot, akkor a cég élete megáll.

    *
    lemaradtam a 2.0-nál - sajna
    Mutasd a teljes hozzászólást!
  • Ráadásul a "verziókövetés" a kettő közül egyiket sem jelenti, és ha egyáltalán valamit ebben a kontextusban, akkor leginkább a szervízhomlokzaton publikált szerződések időbeni változását. A leírás alapján inkább kliensoldali cache-invalidálás ugrik be, szóval itt még rendet kéne tenni fogalomügyileg is.
    Mutasd a teljes hozzászólást!
  • Egeszen pontosan mi is a problemad? - adatbazisban bekovetkezo valtozasokat szeretned figyelemmel kiserni(timestamp), vagy a konkurrens mukodesnel elofordulhato adatvesztest szeretned kikuszobolni(lock)?
    Mi koze ennek a verziokoveteshez(CVS,SVN)?
    Mutasd a teljes hozzászólást!
  • Beszeljuk at a lehetosegeket, elonyoket, hatranyokat.
    Legyen adott egy kliens-szerver alkalmazas, tobb egyideju klienssel.
    Hasznaljunk timestamp-et a record-okhoz? Vegyuk fel a tablaba is? Vagy egyszerusitsuk a problemat a record-ok lock-olhatosagaval?
    Milyen modszer az amit sikeresen hasznaltok?
    Mi az igazi modern modszer ami illik az uj technologiakhoz (WCF, LINQ to SQL,...)

    Varom ertekezeseteket!
    Mutasd a teljes hozzászólást!
abcd