LINQ to SQL használata AJAX segítségével

LINQ to SQL használata AJAX segítségével
2010-07-19T17:04:36+02:00
2010-08-17T18:39:37+02:00
2022-11-18T20:45:38+01:00
Dandi
Tiszteletem!

A kérdésem nagyon egyszerű: hogy lehet értelmesen párosítani az AJAX kérelmeket olyan webszolgáltatással, aminek a visszatérési értéke egy típusos List (vagy IQueryable<T>, IEnumerable<T> stb) (vagyis nem Anonymous type) linq query, amit a LINQ to SQL-el kérdezek le?

Ugyanis több problémába is folyamatosan belefutok:
Van egy adatbázisom, aminek a tábláit berántom designview segítségével LINQ DataContextbe (edmx-be). Lesznek mindenféle tábláim. A konkrét esetben egy ilyen tábla az Articles (egy kisebb hírportál cikkeit tartalmazza a tábla). Persze ehhez a táblához idegenkulccsal mindenféle táblák csatlakoznak, például az aspnet_Users tábla (a feltöltő ID-je az idegenkulcs), vagy a Categories tábla, amibe a rovatok szerepelnek (CategoryID idegenkulcs az Articles táblában).

Ha írok egy metódust az Article (partial) osztályába ami lekérdezi a cikkeket mondjuk így:

public List<Article> GetArticles() { return new ValamiDataContext().Articles.ToList(); }

Aztán egy *.asmx webservice-t vagy WCF-et, ami ezt a lekérdezést meghívja, és végül ezt a [WebMethod]-ot meghívom JQuery/AJAX-al mondjuk így:


$.ajax({ type: "POST", url: "../ValamiWebService.asmx/GetArticles", data: "{}", contentType: "application/json;charset=utf-8", dataType: "json", success: function (msg) { //doWork... }, error: function (msg) { alert("hiba..:"); } });

Akkor az nem fog működni, mert a JSON (se az XML) nem fogja támogatgni a körkörös referenciát, egyszerűen azért, mert a szintaktikája nem engedi. Egész pontosan a következő hibaüzenetet dobja:

A circular reference was detected while serializing an object of type

Persze nem akarom én kihasználni a konkrét esetben kliens oldalon a kétirányú relációkat, ténylegesen csak az Articles tábla oszlopaira (mezőije) van szükségem, de a Serializer a szülő és gyermek kapcsolatok is megpróbálja leképezni majd, és ez nem felülbírálható csak globálisan.

Persze erre az esetre sok nemhivatalos gányolós megoldás található a neten, például az edmx-ben a problémás relációk láthatóságát public-ról internal-ra állítom, de az ilyen, és ehhez hasonló megoldások annyi hátránnyal járnak, hogy tökéletesen használhatatlanná teszik a LINQ-t. Természetesen nem a LINQ a hibás, és az EntityFramework is ugyan ebbe a csapdába esik, egyszerűen a JSON és XML formátumok nem képesek leképezni az ilyen kapcsolatokat.

Ilyenkor azt szokták javasolni, hogy ne típusos List<T>-vel térjek vissza, hanem AnonymousType-al, de ez a megoldás csak akkor működik, ha egyből fel is használom a query-t, mert olyan metódus nincs, hogy: public List<AnonymousType#135> GetArticles(). Persze, akkor miért nem ott helyben készítem el a query-t? Hát azért, mert egyrészt nem server oldali adatkötést használok, hanem JSON-t, másrészt szeretnék réteges felépítésű oldalt írni, ahol nem minden lap codebehind részében van benne egy kósza query, meg pár metódus.

Tehát maradt az, hogy a LINQ legenerált adataihoz nem nyúlnék legfeljebb kiegészíteném, de magával a típusokkal nem térhetek vissza, mert azok egyből elszállnak circular refernce-el, vagyis megalkothatok egy teljen különálló osztály hierarchiát, ahol gyakorlatilag leképezem a LINQ-s generált osztályokat relációk nélkül, hogy normális, használható típussal térjek vissza, de így meg azontúl hogy redundáns kódokkal leszek tele, még átláthatatlan is lesz az egész program.


Tehát: vagyon jó a LINQ és az EntityFramework is, sokat segít, és szeretném is használni, illetve a JQuery és az AJAX kérelmek is nagyon hasznosak asszinkron adatkötésnél, de a kettőt egyszerűen képtelen vagyok összepárosítani, és ha valahogy meg is oldom, nem vagyok benne biztos, hogy az elegáns/jó/értelmes megoldás.

Ti hogy használjátok a LINQ JQuery/AJAX párost, milyen megoldásokat ismertek, vagy mi az, amiről le kell mondanom, és valami mással helyettesítenem?

Remélem érthetően fogalmaztam, és nem túlságosan katyvasz, ha mégis szóljatok mi lett értelmezhetetlen és megpróbálom elmagyarázni. Válaszotokat előre is köszönöm.
Mutasd a teljes hozzászólást!

  • És ha közé teszel egy DTO objektumot ami Serializable?

    Akkor azzal tuti nem lesz körkörös hivatkozás, szerializálni lehet, annyi az egész hogy a Getxxx metódus xxxDTO objektummal térjen vissza.

    Vélemény?

    Morzel
    Mutasd a teljes hozzászólást!
  • Hali!

    Érdeklődnék, hogy lett-e valamilyen használható megoldás a fenti problémára, mert most én is bele futottam és eddig nem találtam semmi használhatót sem...:S Kivéve persze, azt, hogy ha a dbml dizájnerében a táblák közötti kapcsolatoknál a gyerek tábla access tulajdonságát public-ról internal-ra állítom.
    De valahogy nem hiszem el, hogy nincs más, használhatóbb megoldás.
    Mutasd a teljes hozzászólást!
  • Hello!

    Nem sikerült, és ez több mint kellemetlen. Már kísérleti szinten azt is megtettem, hogy létrehoztam egy új database map-et, ahol a relációkat elrejtettem vagy töröltem, és bár így nincs körkörös lekérdezés, egyértelműen használhatatlan megoldás, hiszen oda az objektumorientáltságod, és Isten óvja a következő programozót, aki ki akar majd igazodni a kódon. Van pár ígéretesebb próbálkozás, de ne számíts csodára, nincs elegáns megoldás, egyszerűen a JSON szintaktikája (se az XML) nem fogja támogatni a körkörös referenciát, megkerülni pedig - jelenleg - nem tudod.

    De nézzük én mit találtam végül a legkevésbé borzalmasnak (még így is az):

    van egy jsserializer:
    private JavaScriptSerializer ser = new JavaScriptSerializer();

    aztán lemondasz a típusosságról, és így egy query-t, aminek a típusa anonymoustype lesz. Persze ezzel nem térhetsz vissza, de stringgel bármikor, úgyhogy fogod a query-det, és a jsserializer segítségével karakterláncként elküldöd, ezt már az ajax megeszi.

    valahogy így:
    public string GetImages() { var query = (from img in dbe.Images select new { img.ImageID, img.FileName }).Take(5).ToList(); return ser.Serialize(query); }


    Persze ez is csúnya, mert:
    - Nem erősen típusos a visszatérési érték, így nehezen újrahasznosítható.
    - Csak ajaxnál használhatod, mert nem IQueryable, tehát ha sima ODS-nek akarod átadni ugyanezt server-side, akkor megírhatod a párját erősen típusosan, ami redundáns kódot eredményez.
    - Ha egy mezővel többet akarsz lekérdezni, akkor itt is gondolnod kell rá, hogy kiegészítsd az anonymousType-ot (select new { ... }).
    - és minden ami ezekből következik (ez csak ilyen pongyola lista, hogy mi zavart engem nagyon, még sok más hibája is van, pl a jsser osztály sem az igazi, de legalább nem kell 3rd party megoldásokra támaszkodni új szerelvényekkel).


    Ettől függetlenül, ha valakinek van még valami ötlete, javaslata, megfigyelése, kérdése azt ossza meg, figyelem a topicot, mert még mindig nincsen általános megoldás a problémára.
    Mutasd a teljes hozzászólást!
  • Hello!

    Sajnálom, csak most böktem ki, hogy érkezett válasz, mert a outlook spamnek nyilvánította az értesítőt. A megoldásod még mindig érdekel, de sajnos egyelőre nem értem, hogy mire gondolsz. Tudsz egy példát mutatni, milyen módon valósítanád ezt meg? Utána kipróbálom és véleményezem nagyon szívesen : )
    Mutasd a teljes hozzászólást!
  • Arra gondolt, hogy csinálj egy/több másik osztályt, amire átkonvertálod a linqtosql-es osztályaid. Azaz nem közvetlenül a linq-s entitásokat adod vissza.
    Mutasd a teljes hozzászólást!
  • Értem, ezt fentebb írtam is, hogy árnyék osztályokkal leképezem az osztályokat kapcsolat nélkül, de ez ugyan az, mint a két map lehetősége, és ugyan azokat a hibákat rejti.
    Mutasd a teljes hozzászólást!
  • Ez így van, Isten hozott a csodás ms féle adatelérési technológiák és a wcf közötti együttműködési katyvasz világában! :)
    Mutasd a teljes hozzászólást!
  • Egyébként, rohadjak meg, ha értem, miért nem lehet kikapcsolni, vagy beállítani a reláció mélységét ilyen esetekben.

    Ha vannak cikkeim, és a cikkekhez tartoznak szerzők, akkor persze, hogy körkörös lekérdezést eredményez, hiszen a szerzőknek meg vannak cikkeik, és így tovább. De ez egy b@romság. Ennyi erővel semmilyen relációt ne valósítsunk meg, hiszen ha kétirányú a reláció, akkor úgyis körkörös lesz. Rettentő ostoba megoldás. Nem a JSON vagy az XML hibája ez, ahogy egyébként sokszor emlegetik az MS-nél. Egyszerűen tarkón lő egy nagyon jó megoldási lehetőséget. Elkezdi támogatni az MS a jQuery-t, kihozza a WCF-et, és elkészül az EntityFramework, de azért együtt ne használd, külön-külön meg lóf@szt se érnek.

    Az pedig különösen felháborító, hogy mennyire lesz@rják. Aki nekiállt EF vagy LINQ2SQL segítségével jQuery-ben dolgozni, az bele is futott ebbe a hibába, és jelentette is. Sok cikk értekezik a problémáról és ezernyi fórumon találni kérdéseket róla, de semmilyen hivatalos megoldás nem születik. Az, hogy az auto generated entitás osztályokat egyesével címkézzem attribútumokkal, ahogy javasolják, megint öngyilkosság. Az értelme veszik el. De minden más megoldási javaslattal ugyan ez a baj, átláthatatlan félmegoldások, amik további, és még nagyobb hibákat eredményeznek.
    Elkötelezett híve vagyok az ASP-nek, mert csoda dolgokat lehet vele működni, de ez ledobja nálam a ékszíjat.
    Mutasd a teljes hozzászólást!
  • Én ezért használok sima ado.net-et vagy enterprise library-t, saját generátor szkriptekkel generálom az általános adatelérést, ahol meg nem lehet generálni, megírom, így viszonlag elég gyorsan lehet dolgozni szerintem...
    Mutasd a teljes hozzászólást!
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
abcd