Hur förhåller ni er till att skicka upp en datareader från DAL till BLL? När man tex fyller sina objekt i BLL så har jag sett att man i vissa fall gör det med hjälp av en datareader. För någon dag sedan så fick jag en intressant kommentar gällande det i stil med "det är bättre att skicka upp en datatabell till BLL än en datareader. Detta eftersom det blir en bättre avskillning mellan lagren." Många skickar en lista av poster List<Records>. Fast jag tycker det inte spelar så stor roll - men en sak är viktig. Readern skall stängas så fort som möjligt eftersom den ligger öppen med connection mot databasen tills den stängs. Dataset stängs automatiskt men den å andra sidan tar massor av mer minne, kräm och plats när man arbetar med den så för webben är datareader att föredra så långt det går. Hej, Om DAL ansvarar för att interagera gentemot din datakälla så tycker inte jag att du skall skyffla upp en ordinär datareader från DAL till BLL eftersom att denna har ett beroende direkt mot din datakälla (din connection). Hur menar du då att din DAL skall känna till Entiteterna? Då du inte skall refferera uppåt. Domain.Model.dll dina entiteter Daniel, "Så jag tycker inte allt du är fel ute. Dock är de som pratar DataTabel ute och cyklar." Magnus, "Allt det där du säger är faktiskt något du själv kan ansvara för och effektivesera jämfört med DataTabel. Hmm, jag vill nog påstå att ditt test inte riktigt stämmer och att DataReadern är snabbare. Skillnaden mellan din och min kod vad jag kan se är att du har använt dig av GetString() och GetInt() metoder, det gjorde inte jag eftersom jag använd mig av FieldInfo.SetValue() metoden och bara plockade ut data med dataReader[columnName] utan att bry mig om vilken typ den var. "Något som jag dock upptäckte var att vid en första anslutning mot databasen när det inte fanns någon koppling i ConnectionPolen så tog DataReadern lite längre tid på sig, vilket jag inte kan förklara men när det fanns en koppling i polen så var DataReadern i vissa fall nästan 5 gånger snabbare. " Shit vad insnöat detta blev :-) Ni har tappat en liten detalj.. användningen av minnet.. "MS rekommenderar att man kör DataReader hela vägen för ASP.NET (listor) "DataReader är helt klart bäst ur prestandasynpunkt, men helt klart sämre ur en skalbarhetssynpunkt. Och jag måste säga att jag oftast är lite skeptiskt till MS bestpractis varianter, där det verkar som MS tror att alla sysslar med små hemsidor till fotbollsföreningar... " "Det blir flera gånger snabbare och så klart mer skalbart." Det beror väl på typen av projekt och hur man kapslar in sin logik, okej att man inte skickar DataReadern till BLL men då kan man sköta mappningen i DAL eller ha ett mellanlager som sköter mappning. Niclas, <b>Jag skulle vilja se dig separerar ditt UI, BLL och DAL på seperata maskiner där du skickar en DataReader från ditt DAL upp till UI.</b> Jag vet inte, jag gillar inte riktigt tänket med DAL, BLL osv... "Jag har läst om sådana lösningar i teorin, men aldrig har sett det i praktiken." "Det stämmer att Datareader inte blir bra över process/maskingränser. "det är förstås ett "helvete" att göra förändringar i schemana om man skulle behöva det, så därför brukar man inte ändra utan bara lägga till en ny version och det hela kommer sluta med riktigt "DLL-hell" om man inte får en bra struktur och dokumentation över vilka services som används av vilka program :) " "Och då krävs det bla att separation of concerns är tillräckligt hög. " Kan någon av er som "gör rätt" med tanke på skalbarhet, visa upp exempel på en sådan sajt (borde finnas på Internet om vi pratar extrema krav på skalbarhet?) som är byggd med fysiskt separerade skikt (BL/DAL-DLL:er installerade på en annan server än IIS), skulle vara intressant att se! Om ni har sådana lösningar, har ni gjort mätningar nån gång och säkerställt att sådan lösning verkligen är snabbare än "monolitiska" applikationer som använder IDataReader för att rendera listor? <b>Snabb</b> är fortfarande inte samma sak som <b>skalbar</b> eller enkel att underhålla, men nej förutom de lösningar jag byggt åt kund och Cornerstone så ver jag inga öppna lösningar. Däremot vet jag en mängd med böcker och artiklar som pratar om det som jag gladeligen delar med mig av senare idag. "har ni gjort mätningar nån gång och säkerställt att sådan lösning verkligen är snabbare än "monolitiska" applikationer som använder IDataReader för att rendera listor? " Jag skall ta ett högst verkligt exempel som jag stött på när jag utvecklat. Som de flesta vet så har en IIS 25 trådar (workerthreads) per processor att leka med, det betyder att de som max kan servera 25 samtidiga användare om det finnes en processor, övriga sätts på kö och väntar på att någon annan är färdig. (detta är default värden, och kan labboreras lite med). Magnus. "Du pratar om vikten att sära Ui och Business mellan olika maskiner. OJ Magnus, det var tydligen ett känsligt ämne här eftersom du nu urartar med personangrepp (du undrar om jag är läskunnig!) och VERSALER! Som elak moderator kommer jag nu stänga denna tråd...Skicka en datareader från DAL till BLL?
Vad tycker ni?Sv: Skicka en datareader från DAL till BLL?
Att hålla på att konvertera hit och dit är ibland lite overkill. Det finns så många som överbygger sina applikationer att det nästan tar längre tid med avancerat inkapslade rutiner, funktioner och dynamiska saker. Det gäller att hålla det på en bra nivå.
Bara för att det går att göra något riktigt häftigt men är otroligt komplext så måste man inte göra det. Lagom är bäst.. Det är först vid 2-3 sajten det är dags att försöka bygga något som kan användas på flera ställen och med hög dynamik - men det skall alltid vara något som underlättar, inte försvårar.
Dock är det viktigt att lägga tid på något så viktigt som datalagret - det är ju själva grundpelaren till att kunna bygga en dynamisk webbsida. De klasser jag använt på en mängd sidor fungerar oerhört bra och stabilt utan några som helst problem. Så länge de fungerar behöver jag inte fundera på något mer komplext. Se Artikel [Skapa ett databaslager]Sv: Skicka en datareader från DAL till BLL?
Lätt att du skall använda en Reader. MEN gränsa gärna med Mapper objekt istället.
Dvs.
Entitet
MapperObjekt <--- Kännder till Entitet och Reader
Data Access
Mapperobjektet är det enda objekt ihop med Data Access som känner till readern.
Entiteten har inte sådan info utan är bara fylld klass.
MapperObjektet har som uppgift att ladda, spara, updatera m.m. Den i sig blir din avskiljare.
Att använda DataTabel är bara dumt, dels är de stora o klumpiga, de tar minne, de genereras
själva utifrån en reader. Så du kommer bara få onödig data mapping här.
Ex säg att:
Entieten User har ett MapperObjekct vid namn UserRepository
UserRepository använder något slags dal. O/R Mapper, ADO eller vad som.
User user = UserRepository.GerUserById(234);
UserRepository är det enda objekt i din BLL som får känna till Data access bitarna alla andra
klasser i BLL gör det inte. Så som Servcie klasses, Factories etc...
varje entitet har typ sin egna Repository som nyttjar gemensamma Data access objekt.
Som Pelle säger, se bara till att du stänger Readers. Vill du vara mer FRÅN kopplad från DA (Data Access biten) använd IDataReader så blir du mer frånkopplad från DAt. Dvs ditt DA ger dig en IDataReader som är ex. SqlDataReader.
Så jag tycker inte allt du är fel ute. Dock är de som pratar DataTabel ute och cyklar.
Mvh JohanSv: Skicka en datareader från DAL till BLL?
Sv:Skicka en datareader från DAL till BLL?
Dvs.
BOL = Entiteter, Sercvice, Factories, etc...
DAL = Data Access komponenter, ADO .Net, SQLHelper m.m.
Mvh Johan
Sv: Skicka en datareader från DAL till BLL?
Domain.Logic.dll (dåligt namn)
Domain.Providers.dll (typ dal)
Logic --> Providers
Logic --> Model
Providers --> Model
Ponera att DataReaders samt Connection hade legat i en egen System.Net-dll så vill man ju egentligen bara att DAL skall ha referens till denna och inte BLL.Sv:Skicka en datareader från DAL till BLL?
Det ger ändå inte svar på din kommentar:
" så tycker inte jag att du skall skyffla upp en ordinär datareader från DAL till BLL "
DAL = Data Access layer, för att mappa entitet med data från ex DB måste du låta BLL
känna till din data container, dvs i detta fall ex DataReader (om man kör manuel mapping)
Kör man O/R mapper så kommer den i sig använda readers för att fylla objekt. Det blir dock bara
ett extra litetet lager mellan BLL och din DA.
Mvh JohanSv:Skicka en datareader från DAL till BLL?
Det finns 2 fördelar med att använda en DataTable jämfört med en DataReader. Och det är 1 att du får en skarp avskiljning mellan dina lager, ditt DAL är inte beroende av att någon klåpar i ett BLL skall hålla koll på att din koppling till databasen stängs korrekt. Bara tanken på att jag bygger ett DAL som någon annan kan använda som inte riktigt har koll på hur viktigt det är att databaskopplingen stängs korrekt gör mig nervös.
Det andra är att man som alltid vill ha sin databaskoppling öppen så korttid som möjligt eftersom oftas så är man inte själv om databasen och dessutom så styr man inte själv när koden exekveras eftersom trådarna skiftas när man minst vill det. Så att skicka tillbaka en DataReader till ett BLL där programmeraren lyckas med konstycket att lägga in ett anrop till en webservice i sin loop för att fylla sin objekt med data, medans databasen är öppen kommer ge dig stora prestanda problem om du får lite last på din applikation, och din databas kommer inte uppskatta dig om den serverar flera olika applikationer.
Att ett DataTable är tyngre och lite mer prestandakrävande än en dataReader är något jag kan leva med och speciellt min DBA när jag i slutändan ger databasen betydlig mer arbetsro.
Den enda fördelen en DataReader har mot en DataTable är att den är snabbare när den används korrekt och eftersom du lämnar i från dig ansvaret för att använda den korrekt när den lämnat ditt DAL, och där du dessutom inte har en anning om hur länge din koppling till databasen kommer vara öppen, så skulle inte jag lita på att den kommer användas korrekt.
Därför tar jag mer än gärna den lilla prestandahit som en DataTable medför, hellre skalbarhet än prestanda...
- MSv: Skicka en datareader från DAL till BLL?
Allt det där du säger är faktiskt något du själv kan ansvara för och effektivesera jämfört med DataTabel.
För det första stänger man ALLTID sin reader när man är klar med den. Det är typ en lag på det :-)
DataTabel är ytterliggare en onödig mappening något du faktiskt kan göra själv för att slippa göra det två gånger.
En annan kul grej är att många utvecklare är så insnöade på att alla deras lager skall vara så utbytbara som möjligt. varför? Ok det är tjusigt, men hur många har egentligen behövt byta ut dem?
Kör man dessutom interface drivet har man inge som helst problem att få transparanta lager som är utbytbara även om man nyttjar en IDataReader.
Att mappa från DataTabel kräver to m. lite mer tidsarbete än en datareader om man skall va fjollig på antal tecken man måste skriva för varje post man vill plocka ut. (Nu föredrar jag dock en O/R Mapper så man slipper manuell mappning).
Jag bygger dock system efter DDD (Domäin driven design) och inte efter gamla BLL och DAL arkitektur historian då den inte alls faller mig i smaken. DDD har to m. gett mig mer fördelar och mindre problem än BLL och DAL mest pga sin flexibilitet gällande just Mappning och databashantering.
Sen bygger jag inte DB först, utan Domäin först och sen DB efter min domäin, detta för att DBn är en container av data den skall inte "VARA" ens applikation. Många bygger tyvärr DB först och blir låsta till DBns struktur och på så vis blir ens applikation beroende av sista skiktet gällande ändringar och alla skikt samt lager blir lidande till skillnad från en DDD applikation då du mer eller mindra kan göra alla dina justeringar i Domänlagret utan att bry dig om din DB eller att din DB kommer påverka din applikaton.
Så egentligen är DataReader vs DataTabel en designfråga, en smaksak. Det finns egentligen inget rätt eller fel. Lika väl som vissa vill känna sig mer frånkopplade ett DAL (ett lager jag i princip inte har längre på samma sätt) så är DataTabel en bunden container till ADO, så vill man nyttja annan datakälla är man låst till just ADO. IDataReader går att mocka utan problem.
Mvh JohanSv:Skicka en datareader från DAL till BLL?
För det första stänger man ALLTID sin reader när man är klar med den. Det är typ en lag på det :-) "
Man får inte köra förfort med sin bil heller, det finns lag på det med, och ändå kör folk förfort... Tro mig alla människor stänger inte sin reader, inte ens alla stänger sin databaskoppling. Man kan inte utgå ifrån att alla programmerar är lika duktiga som en själv...
"En annan kul grej är att många utvecklare är så insnöade på att alla deras lager skall vara så utbytbara som möjligt. varför? Ok det är tjusigt, men hur många har egentligen behövt byta ut dem?
Kör man dessutom interface drivet har man inge som helst problem att få transparanta lager som är utbytbara även om man nyttjar en IDataReader. "
Nu var det inte att de skulle vara utbyttbara som jag hävdade, utan att varje lager tar hand om sina uppgifter och inte låter andra lager sköta uppgifter som bör ligga i ursprungslagret.
"DataTabel är ytterliggare en onödig mappening något du faktiskt kan göra själv för att slippa göra det två gånger. "
Visst är det det, men som sagt, min öppna databaskoppling är betydligt viktigare för mig än de extra millisekunder det tar att mappa 2 gånger. Jag har gjort en helt ovetenskapligt test på att mappa objekt dels från en DataReader och dels från en DataTable, samt mätt tiden som databasen är öppen.
Det var en helt vanlig user tabell, men 100000 poster och 9 kolumner.
För 100000 poster såg det ut så här...
Hämta och mappa data med datareader 998 ms...
Hämta och mappa data med datatable 2030ms... databasen öppen 890 ms.
För 10000 poster såg det ut så här...
Hämta och mappa data med datareader 99 ms...
Hämta och mappa data med datatable 156ms... databasen öppen 54 ms.
För 1000 poster såg det ut så här...
Hämta och mappa data med datareader 12 ms...
Hämta och mappa data med datatable 15ms... databasen öppen 5 ms.
Och då finns det ingen som helst logik i konstruktorn för objekten, utan den sätter bara värden med hjälp av SetField() på fieldInfo, på ett objekt.
Så den extra ms det tar att mappa med hjälp av en dataTable tar jag gärna när jag ser att databasen är öppen halvatiden jämfört med datareader, samt att jag vet att ingen klåppar glömmer stänga databaskopplingen eller får en flipp och lägger något tungt i konstrktorn för varje objekt som ändrar tiden drastiskt.
Nu var det dessutom så att det bara var en tråd igång, om jag hade slängt in lite fler trådar så hade connectionpoolen för dataReader tagit slut fortare än för datatablen och tiden för att skapa kopplingen och mappa öbjektet hade ökat, vilket kanske hade gjort att det faktiskt tagit längre tid med datareadern än med datatablen. Rent teoretiskt så skulle datatable kunna hantera dubbelt så många trådar än datareader innan connectionpoolen tar slut, vilket kommer att öka prestandan med framförallt skalbarheten i applikationen.
"Så egentligen är DataReader vs DataTabel en designfråga, en smaksak. Det finns egentligen inget rätt eller fel."
Skönt då är jag inte helt ute och cyklar då ;)
- MSv: Skicka en datareader från DAL till BLL?
Jag vet inte hur ditt test ser ut, men jag fick dessa tider när jag hämtade ut 10.000 rader med 4 st kolumner. En person hade ett id, förnamn, efternamn och en ålder.
Person objektet mappades med en datareader, medans DataTablen enbart laddades in.
Jag kollade tyvärr inte trace i SQL Servern, men anser dock att den kan vara lite missvisande då en trace slöar ner SQL Servern (lite) och på så sätt kan det ge mer tid till den exekverande koden medans den andra exekverande koden kan få vänta.
Något som jag dock upptäckte var att vid en första anslutning mot databasen när det inte fanns någon koppling i ConnectionPolen så tog DataReadern lite längre tid på sig, vilket jag inte kan förklara men när det fanns en koppling i polen så var DataReadern i vissa fall nästan 5 gånger snabbare.
---- DataReader ----
00:00:00.0160000
00:00:00.0120000
00:00:00.0160000
00:00:00.0130000
00:00:00.0130000
00:00:00.0180000
---- DataTable ----
00:00:00.0440000
00:00:00.0280000
00:00:00.0330000
00:00:00.0310000
00:00:00.0290000
00:00:00.0420000
Källkoden finns att hämta här, säg till om det finns några orättvisor åt något
http://www.nickenyfiken.se/temp/DataReaderVsDataTable.zipSv:Skicka en datareader från DAL till BLL?
Och det helt enkelt av den anledningen att jag inte är intresserad av att skapa alla mina objekt, på det sättet som du gör med Factories, utan isället mappar in de i objekt som en ORMapper.
Redigerat:
Nu har jag testat min kod lite mer och upptäckte ett märkligt fenomen.
1. Om jag har alla mina variabler public och använder typeOf(User).GetType().GetFields() för att hämta information om fälteten så tar det längre tid att använda en DataReader och fylla objekten än vad det tar för DataTablen att hämta data...
2. Om jag däremot har mina variabler public eller Private med skickar med BindingFlags.Public eller BindingFlags.NonPublic så går det nästan 5 gånger så snabbt för datareader att fylla objekten med data jämfört med dataTablen att hämta sin data.
Så jag får nog revidera min åsikt om att det går fortare med en datatable än med en datareader. Får väl mappa upp dataReader mot en collection object som innehåller namnet på kolumnen och värdet från databasen i min DAL, så jag slipper skicka tillbaka en dataReader eller en DataTable :)
- MSv:Skicka en datareader från DAL till BLL?
Jag tror inte det har med kopplingen att göra utan att SQL Servern cachar Exekveringsplanen, vilket gör att du får snabbare svar från sqlservern andra gången du ställer samma fråga mot den, precis som du fick en prestandaökning i gammla SQL Servern när man använde sig av SP, så får du samma ökning nu med andra (samma) frågan mot databasen.
- MSv: Skicka en datareader från DAL till BLL?
>Man får inte köra förfort med sin bil heller, det finns lag på det med, och ändå kör folk förfort... Tro mig alla människor stänger inte sin reader, inte ens alla stänger sin databaskoppling. Man kan inte utgå ifrån att alla programmerar är lika duktiga som en själv...
Nu råkar jag kräva en fas som heter "Kodgranskning" kör Agile metoden. Så vi har inte detta problem.
Men visst finns det.
Det är mkt som skall till för vara en pragramatic programmer.
Nu finns det i alla fall svar på topicen, och det är nu helt upp till Krister att faktiskt välja det som passar
hans och hans teams arbetsätt bäst.
Mvh JohanSv:Skicka en datareader från DAL till BLL?
Om man implementerar som förslag #1 och smäller upp DataTable 50k -> CustomObjects 50k -> DataGrid 50k så kostar det ju betydligt mer både för minne (GC) och CPU än att helt enkelt returnera en DataReader från DAL som man binder till en Grid. (Jag pratar nu uteslutande om Select av listor och ASP.NET). DataReader allokerar små chunks a 4096 bytes som blir HTML on the fly i stället för att gå via att allokera tusentals extra objekt som direkt kastas bort. Det blir flera gånger snabbare och så klart mer skalbart.
MS rekommenderar att man kör DataReader hela vägen för ASP.NET (listor)
Developing High-Performance ASP.NET Applications
http://msdn2.microsoft.com/en-us/library/5dws599a.aspxSv: Skicka en datareader från DAL till BLL?
Developing High-Performance ASP.NET Applications"
Jag skulle vilja se dig separerar ditt UI, BLL och DAL på seperata maskiner där du skickar en DataReader från ditt DAL upp till UI.
DataReader är helt klart bäst ur prestandasynpunkt, men helt klart sämre ur en skalbarhetssynpunkt. Och jag måste säga att jag oftast är lite skeptiskt till MS bestpractis varianter, där det verkar som MS tror att alla sysslar med små hemsidor till fotbollsföreningar...
Dessutom så har jag aldrig råkat ut för problemet med att minnet tar slut på någon server, däremot så har jag råkat ut för tomtar som inte stängt sin databaskoppling och vips så stod vår produktionsdatabas och sa att inga fler kopplingar fick göras, det var inte så kul :-)
- MSv:Skicka en datareader från DAL till BLL?
Håller lite med ang din skeptiska syn här, men rörande prestanda. Ja... jag skulle själv ALDRIG kasta en reader ända upp i UI utan döda det precis mellan Domän och Data access gränsen dvs i mina repositories som ex kan nyttja ADO eller O/R mapper som i sig nyttjar ADO...
Mvh JohanSv: Skicka en datareader från DAL till BLL?
Jag skulle vilja hävda att datareadern gör mer skada än nytta för skalbarheten. Bara för att det går snabbt betyder inte det att det är skalbart.
Vad gäller att hämta upp enkla listor oh snabbt göra om dem till HTML så är readers snabba, men vad händer när du vill utföra någon form av logik, eller göra komplexa beräkningar baserat på en datamängd och inte bara en rad? Eller vad händer när du vill försöka återanvända datastruktur i din lösning?
Reders är nog så snabba, men det till kostnaden av att andra attribut får sämre poäng. Sv:Skicka en datareader från DAL till BLL?
Jag tycker t.ex. att sql queries inte hör hemma i BLL och därför tycker jag att det skulle finnas ett lager mellan BLL och DAL som sköter både mappning och sql queries. Detta kan ersättas med en bra OR/Mapper :).Sv: Skicka en datareader från DAL till BLL?
Men hur når ditt lager under BLL ditt BLL? Dina entiteter som du mappar mot ligger ju där.
Det är lite detta som är det kluriga.
Tar vi DDD som exempel så har alla entitets rötter (låt säga entiteter bara för göra det lättare)
en egen Repository klass döpt efter sig (nomalast att göra så pga spårbarhet).
Ex Car har CarRepository. CarRepository i sig ligger i Domänlagret som i sin tur är ett BLL men
lite lite lite DAL oxå. Dessa Repositories är det som pratar mellan data källor och dina domänobjekt.
Anropskedjan är typ.
Entitet -> EntitetsRepository -> Något DA (O/R Mapper/Manuel mappning)
Den manuella mappningen kan vara en DataReader, en DataTabel en XML fil, en OO databas etc etc... Spelar ingen roll. Det är dock i repositoriesarna man kan göra frikopplingen mellan Domän och DA.
På olika sätt. Kör man med en O/R Mapper ex NHib eller NPersist eller Linq to SQL behöver man inte bry sig om datacontainern då dessa sköter det fint åt dig. Mappar du själv ja få behöver du bry dig mer.
I 98% av fallen klarar man sig mkt väl genom att mappa med en IDataReader.
För mer komplexa saker kan en DataTabel fungera sånt som kanske gör mer jobb för dig som programmerare. Dock tycker jag att man skall använda sina entiteter så mycket som möjligt då DataTabel faktiskt är objekt precis på samma sätt fast kan vara mycket tyngre i minnet...
Rörane SQL quesries så kan dessa ligga i ens Repositories så på sitt sätt kommer det i BLL men eftersom ett domänlager i DDD inte är rent BLL utan lite DAL så gör det inte så mkt.
Det viktigaste med lager etc är att man skall ha en god kännedom VART man faktiskt har sina saker.
Det är inte lika viktigt att ens lager skall vara transparanta om de inte är ramverk som måste det för andra lätt skall byta ut dem. Har sett folk som lägget mkt energi på göra så Transparanta lager som möjligt. Det blir oftast YAGNI (you aren't goonna need it) över det hela. Hur ofta har man bytt databas? utan att ens behöva göra om sitt DAL? hur ofta byter man ens ut sitt DAL?
Repositories är dock minst lika utbytbara om man gör dem utbytbara svårare än så är det inte.
Mvh JohanSv:Skicka en datareader från DAL till BLL?
Det stämmer att Datareader inte blir bra över process/maskingränser.
Men hur ofta har du DAL/BL på en separat maskin, ej webbservern?
Jag har läst om sådana lösningar i teorin, men aldrig har sett det i praktiken.
I 999 fall av 1000 (underdrift, och inte bara fotbollsföreningar) installeras ASP.NET system på en maskin, och alla dessa system kommer alltså få sämre prestanda om man utvecklar för att kunna skikta på flera fysiska maskiner.
Det här har stor betydelse i förlängningen för delade miljöer. När alla ASP.NET-applikationer på ett webbhotell slösar på minne och CPU, då märks det.Sv:Skicka en datareader från DAL till BLL?
Utan jag kan mer tänka mig att DAL ligger underst, sedan kommer DomänLagret vid sidan om RepositoryLagret och sedan ovanför där har du ett eventuellt BL lager med Faqades osv.
Kanske blir lite mycket uppdelning men så vill jag gärna se det.
Man kan mycket väl tänka sig att RepositoryLagret ligger jämnsides med både Domänlagret och BL lagret... :S.
Men numera jobbar jag mest med NHibernate så jag behöver inte tänka så mkt på det. Men jag försöker ändå kapsla in NHibernate så att man inte arbetar direkt mot Sessionen i gui:t det känns fel.Sv: Skicka en datareader från DAL till BLL?
Jag har, och dessutom implementerar några stycken. Och faktiskt så är det ganska vanligt idag att man gör så, även om man inte definerar sina lager som BLL och DAL, utan helt enkelt kallar dem för services.
Hela SOA filosofin bygger på att man separerar sina tjänster/services i mer fysiska lager än bara en n-tier lösning på samma maskin. Prestandan blir så klart lidande, men skalbarheten ökar och framför allt så ökar återanvändningen av kod, och underhållet av kod blir betydligt enklare, det är förstås ett "helvete" att göra förändringar i schemana om man skulle behöva det, så därför brukar man inte ändra utan bara lägga till en ny version och det hela kommer sluta med riktigt "DLL-hell" om man inte får en bra struktur och dokumentation över vilka services som används av vilka program :)
För att gå ett steg längre i skalbarheten och prestanda så har jag varit med och implementerat ett cachesystem som låg utspritt på 4 olika maskiner med hjälp av COM+ och Broadcasting över MSMQ. Det var rätt häftigt att implementera och för att göra den komplicerade lösning rättvist så var det inte databas data som cachades, utan data som var uträknat och insamlat via flertal olika anrop till olika services, och som skulle kunna serva en webgarden.
- MSv: Skicka en datareader från DAL till BLL?
Men hur ofta har du DAL/BL på en separat maskin, ej webbservern?
Jag har läst om sådana lösningar i teorin, men aldrig har sett det i praktiken.
I 999 fall av 1000 (underdrift, och inte bara fotbollsföreningar) installeras ASP.NET system på en maskin, och alla dessa system kommer alltså få sämre prestanda om man utvecklar för att kunna skikta på flera fysiska maskiner.
Det här har stor betydelse i förlängningen för delade miljöer. När alla ASP.NET-applikationer på ett webbhotell slösar på minne och CPU, då märks det."
Som sagt, hög prestanda är inte samma sak som skalbart. Eller speciellt underhållbart heller för den delen. Readers är bra på att snabbt hämta information, den är inte lika bra att behandla information.
Visserligen är det så att många lösningar är monoliter driftmässigt, men i princip alla lösningar jag sett har tydliga "separation of concerns" för att lättare kunna återanvände och underhålla och om det skulle krävas, skala ut.
En annan sak är att så länge du bara behöver presentera information enkelt och direkt från dbn då klarar du dig med readers, men så fort du behöver lite bussiness logic så står du dig slätt.
Och nej det är inte ett alternativ att i vissa fall ha readers och i andra fall ha andra typer av lösningar, en applikation som inte är konsekvent är en mardröm att underhålla.
Sen är det också så att kraven på integration lösningar i mellan (SOA / EIA) blir högre och högre, att då bygga en lösning som kräver att du bygger nytt för att tillåta integration är ju rätt ondöigt när det inte krävs så mycket mer i insats att bygga det ordentligt separerat.
Udi Dahan "The Software Simplicicst" brukar säga ngt ganska klokt, "E-bay didn't know they where building ebay five years ago". Han åsikt är i princip att även om du inte behöver bygga för en miljon användare och komplex affärslogik idag så gör du bäst i att ändå se till så att din lösning klarar den förflyttningen så smärtfritt som möjligt om / när den dagen kommer.
Och då krävs det bla att separation of concerns är tillräckligt hög.
F-Ö behöver man inte prestanda optimera innan man har ett problem. Det som drar mest prestanda är inte att ha data i minnet eller lägga det där utan det är accessen mot persistenta medier som databaser tex.Sv:Skicka en datareader från DAL till BLL?
Det är det du har en service repository till, exempelvis en ESB ;)Sv:Skicka en datareader från DAL till BLL?
Det värsta jag varit med om när det gäller arkitekturen för en lösning innehöll upp till 14 olika lager bara för att hämta data.
Överst hade man Sitt Frontend, Web eller Win, under detta lager hade man något som kallades UIProcess, tanken var att man skulle kunna skifta mellan Web och Win utan att behöva ändra något som fanns nedan för.
UIProcess anropade sedan en ServiceAgent Factory för att få tag i en ServiceAgent för att anropa ner till BLL. Som antingen kunde ligga som en referens eller som en webservices, detta kunde man configurerar i sin config-fil så att man enkelt kunde skal ut till en annan masik om det skulle behövas.
BLL bestod sedan av 4 olika lager, ServiceInterface som var interfacet för BLL som anropades från Frontendens ServiceAgent (det fanns lika många serviceInterface som det finns ServiceAgents i Fronenden, typ 1 för varje kommunikations protokoll, alltså i detta fall 2, en för direkt referens och en för soap. Sedan hade man själva BLL (som kunde bestå av flertalet olika projekt) BLL anropade sedan en Factory för att få tag på en ServiceAgent för att hämta data i någon datakälla (direkt eller soap).
Alla datakäller byggdes sedan som services med serviceinterface för både soap och direkt referens, och dessa datakällor delades sedan in i flera sikt, oftas 3: ServiceInterface, BLL, och DLL, ibland fler om det skulle hämtas data från någon annan services istället för databasen.
Utöver dessa så fanns det "separata lager" som innehöll Entiteter och Definitioner (så som exceptions, event, interface mm)
Där hade man verkligen tagit höjd för att kunna skala ut till max, kan tyckas om overkill, men mycket av den logik kod som de utvecklade för en applikation i BLL-lagret ville användas av andra applikationer så på detta sätt var det extremt enkelt att bara lägga ut den som en webservices, man wrappade bara sina metoder i BLL i ett ServiceInterface som bestod av en webservice och så var det "up and running".
Det var dock rätt tråkigt att lägga till en ny metod, eftersom den metoden skulle implementeras på typ 10 olika lager och det mesta bestod var bara en wrappning av lagret under utan någon som helst logik.
Som tur väl så hade man gjort en Template i VS så att lagrena skapades utifrån en mall, så man slapp sitta och skapa alla olika lager så fort man skulle börja göra en applikation.
- MBenchmark?
(Eller har ni nån länk till en sida som presenterar en sådan jämförelse?)Sv: Benchmark?
Sv: Benchmark?
Jag börjar undra om du är läskunnig? Du verkar inte förstå skillnaden mellan skalbarhet och prestanda. Låt mig klargöra detta EN GÅNG FÖR ALLA. IDataReader är bäst ur prestanda synpunkt, att bygga skalbart kommer aldrig att vara snabbare än att bygga för prestanda om du bara tittar på enstaka anrop och göra så simpla saker som att rendera listor på en websida. ÄR DET FÖRSTÅTT, KAN DU SLÄPPA DET NU.
Man bygger skalbart för att det finns massor med fördelar med detta när det gäller att fysikst kunna skilja på olika skikt. Dels ur hanteringssynpunkt men även en sådan viktig aspekt som säkerheten, om du lägger en brandvägg mellan ditt UI och ditt BUSINESS lager så får du en extra säkerhet på den maskinen som antagligen kommer kräva mer rättigheter, du kan exempelvis göra så att din Webserver omöjligt kan komma åt någon annan maskin än just Businessmaskinen och det betyder att det blir ytterligare ett hinder att forcera om man vill hacka sig in.
Dessutom så kan det vara så när det gäller skalbarheten att du börjar nå maxbelastningen på din webserver med minnet och processorerna, en lösning blir här att flytta ut businesslagret till en separatmaskin som tar hand om den biten och där med frigör resurser på din webserver. I ditt fall så hade du varit tvingad att istället för att lägga businesslagret på en maskin, så hade du köpt in en webserver till, men oopss, det går ju inte så bra, utan du måste så fall börja då de lastbalanserade, så att samma domän går till de olika maskinerna, och vips så fick du licenskostnader som motsvara 4 nya maskiner. Dessutom så när ju sysslar med lastbalansering (på rätt sätt) så vet du inte vilken webserver som kommer att träffas vid nästa anrop, så att använda sessioner i sin website, blir mycket mer komplext eftersom du så fall måste flytta ut de på någon extern maskin.
"Kan någon av er som "gör rätt" med tanke på skalbarhet, visa upp exempel på en sådan sajt (borde finnas på Internet om vi pratar extrema krav på skalbarhet?) som är byggd med fysiskt separerade skikt (BL/DAL-DLL:er installerade på en annan server än IIS), skulle vara intressant att se!"
Tja det flesta större siter, typ amazon och dell är garanterat uppbyggda på detta vis, är övertygad att Google också har en backend som ligger och indexerar alla sidor och håller de i internminne på ett jättekluster i bakgrunden och sedan har några maskiner som står som i en webbfarm för att serva html-anrop. Men eftersom jag inte byggt dem så har jag svårt att bekräfta det.
- MSv: Benchmark?
Nu tar vi och skapar en site, där finns 4 sidor var av 3 av sidorna är subbersnabba, tar någon ms att rendera, men den ena sidan har ett tungt businesslager som skall göra massor med beräkningar och hämta data från andra källor, denna sida tar lätt över 3 sekund att rendera.
Om du nu får 25 stycken samtidiga användare att kalla på denna långsamma sida, så kommer resterand av din besökare vara tvungna att vänta minst 3 sekunder innan de kan få se sin sida som endast tar någon ms att rendera. Här står du idag, eftersom du inte byggt skalbart, utan bara tänkt på prestanda, all din logik ligger i din codebehind som kallar till alla olika datakällor och gör sina beräkningar.
Jag däremot har byggt exakt samma site, men separerat mina lager åt, jag får samma problem som dig och lägger ut mitt businesslager på en externmaskin och gör anropet ditt. Nu kommer det inte hjälpa mig eftersom min tråd fortfarande står och väntar på att jag får svar tillbaka, så jag tar fortfarande 25 trådar i anspråk. MEN MEN, nu finns det något så fiffigt som heter asyncrona anrop i .NET vilket gör att jag kan starta min sida i en workerthread, göra ett anrop i en vanlig tråd och släppa tillbaka workerthreaden till ASP.NET's threadpool (sidan står nu i väntläge på att få svar tillbaka från mitt anrop) och när svaret kommer så plockar jag en workerthread från poolen och kan rendera färdigt sidan. Jag har här med släppt min låsta tråd tillbaka till ASP.NET som kan processa de andra requesten av sidorna som anropas.
Frågan från mig till dig blir nu, vilket site tror du besökarna tycker ha bäst prestanda, din site där man får vänta i minst 3 sekunder på att sidan vissas när man uppnåt en kritiskmassa, eller min site där man processar sidan direkt. Jag kan ju dessutom separerar mitt BLL lager på flera maskiner så jag låter alla anrop från den långsamma sidan anropa en maskin, och alla anrop från de snabba sidorna anropa en annan maskin.
Jag kan alltså med 3 maskiner klara av betydligt fler besökar än vad du skulle klara av på 3 IIS Serverna i en klusterlösning + en frontend maskin, och där du dessutom får en betydligt högre licenskostnad än vad jag skulle ha.
För att illustrera det med ett enkelt räkneexempel så kan du med 100 samtidiga besökare fylla kvoten för att få vänta de 3 sekunder som de långsamma sidan tar. Så om du har 3 maskiner som står i ett kluster så klara du 300 samtidiga besökare.
I mitt exempel så har jag 1 webbmaskin och varje sida tar säger vi 5 ms (långsammare än din snabbaste på 2 ms, men betydligt snabbare än din 3 sekunder), de 5 ms är så länge som vår workerthread är upptagen med att processa något, så som max håller jag 25 workerthreads i 5 ms, innan någon släpps och nästa användare kan komma till. Om jag då sätter att min max väntetid för användaren skall vara 3 sekunder (det är ju din väntetid vid 300 samtidiga användare) så får jag alltså 3000 (ms) / 5 (ms) = 600, jag har alltså möjlighet att göra 600 5ms block med användare och i varje block så kunde jag ha 25 användare. jag kan alltså teoretiskt hantera 15000 samtidiga användare på en maskin mindre än dig, när du hanterar 300 samtidiga användare. Dessutom så kan kommer mina besökare att uppleva min site som betydligt snabbare än din när samtidiga användare har passerat 300, jag kommer först få samma svars tider som du vid 15.000 användare som du har vid 300. Nu är det teoretiskavärden och andra faktorer kommer påverkar detta långt tidigare.
Har jag byggt min kod rätt från början så tar det mig max 2-3 dagar att implementera dessa asynchrona anrop, medans det skulle ta dig bra mycket längre tid att dela upp din kod i flera lager och för att inte tala om testerna som du måste göra eftersom du ändrat i logiken i din kod.
Jag tycker du skall fortsätta bygga dina siter med DataReaders hela vägen upp, eftersom du tydligen inte har behov av att kunna separerar din lager, det viktigaste för dig verkar vara få extrem prestanda, och när du ändå gör det, så se till att lägga SQL Servern också på IIS:en så slipper du ju de extra micorsekunder som det tar att göra nätverksanropet, prestanda före allt annat...
Välkommen till verkligheten.
- MSv:Benchmark?
Du pratar om vikten att sära Ui och Business mellan olika maskiner.
När du skalar ut ditt uI på flera Maskiner skalar du då även ut business maskinen? Om inte kommer du ju ändå uppnå prestanda problem då denna helt plötsligt blir belastad av flera maskiner.
Att skapa ut UI brukar hjälpa ett litet tag. I vissa fall är det to m bättre att faktiskt ha UI och Business på samma maskiner som skalas ut istället för att splittra lager i skikt.
Jag vågar hävda att det inte massa olika skalbarhetslösningar och allt faktiskt hänger på vilka användarna är och hur många de är och vad de gör. Kolla ex. Lunarstorms eller Play a heads miljöer där de har mkt skriva och läsa samtidigt. De har en rad problem att lösa här.
Sedan finns det de system som har många användare med typ nästan enbart läsning, se Google, Amazon m.m.
Sen finns det de system med mycket skriva och lite läsa. Hur man än vrider och vänder på saker så är det viktigaste att först ha en klar bild över sina krav för att sen ta fram en passande arkitektur.
Precis som du också nämner, i vissa fall behöver man inte ens tänka på skalbarhet för att ens applikation kommer kanske bara användas av max 50 samtliga användare och applikationen kanske inte alls är businesskrävande eller nått...
Det många gör fel idag är att de skall bygga så löskopplade, prestanda och skalbara system som det bara går för att MS tyvärr en gång la fokus på prestanda.
Jag vet inte hur många projekt jag vart inblandad i där folk envist skall bygga efter prestanda är design av sin modell. To m vart så sjukt så ett system som skulle användas av en person satt vissa och prestanda optimerade så mycket de bara kunde, helt utan vinst. Tokigt.
Som Patrik också nämner i sin text, det är viktigt att bygga en arkitektur/design som faktiskt enkelt går att optimera och to m skala ut. Det enda som egentligen behövs är förståelsen över sin domän samt kunskaper om löskoppling och en god design.
Nu tycker jag personligen denna tråd börjar bli för tjatig... Och vissa har redan börjat närma sig personangrepp. Skärpning här... OK?Sv: Benchmark?
När du skalar ut ditt uI på flera Maskiner skalar du då även ut business maskinen? Om inte kommer du ju ändå uppnå prestanda problem då denna helt plötsligt blir belastad av flera maskiner.
Att skapa ut UI brukar hjälpa ett litet tag."
Som jag nämde i mitt förra inlägg så skalade vi ut businesslagret på 2 olika maskiner så att de tunga beräkningar hamlade på en maskin och de lätta delarna hamlade på en annan, helt enkelt av den anledningen att man envisades med att det skulle vara webservices (andra program i java skulle kunna komma åt funktionallitetn) som kördes i IIS:en så hade vi ju inte vunnit något eftersom de begränsas precis på samma sätt som websidorna gör. Om man däremot hade använt något annat protokoll typ Remoting eller egenskriven TCP/IP kommunikation så hade det inte blivit samma begränsningar.
Så i detta fall så skalade vi faktiskt ut business lagret på 2 maskiner och la samtidigt websidorna på 2 maskiner, och givetviss så var det 4 sidor som siten bestod av utan flera..
"I vissa fall är det to m bättre att faktiskt ha UI och Business på samma maskiner som skalas ut istället för att splittra lager i skikt."
Visst är det så, om man inte gör något speciellt i sitt businesslager så finns det ingen som helst anledning att skala ut det på flera maskiner, om man bara hämtar data och skickar tillbaka det till sidan, så finns det ingen anledning att flytta ut det på en annan maskin, men om man logisk separerar skikten åt så har man enklare att separerar det fysiskt om kraven ändras i framtiden, och de tycker iallafall jag är bra mycket viktigare än att tjäna någon ms på att bygga hela sin logik i codebehind-filerna.
"Nu tycker jag personligen denna tråd börjar bli för tjatig... Och vissa har redan börjat närma sig personangrepp. Skärpning här... OK?"
Om du menar mitt inlägg, så står jag för det, då både jag och patrik hade klargjort att en datareader var snabbare ur ett prestanda perspektiv och att skalbarhet "förstör" prestandan, att sedan återigen bli påhoppad med att vi skall bevisa att skalbarhet är "snabbare" än en sida optimerad med ren prestanda är irriterande. Det blir bara en fråga om när och hur man mäter prestandan...
- MSv:Benchmark?
Du verkar ha en nästan religiös inställning till "din" systemarkitektur.. ta det lugnt.. Det ÄR faktiskt okej att ha olika förslag på lösningar, olika erfarenheter, och att dela med sig av det..
Trampade jag på en öm tå eller?
Jag förstår (trots att jag inte gillar ditt tilltal) att det finns poänger med att bygga skalbart på detta sätt, om behovet finns.
Pratar vi 15.000 samtidiga användare (requests egentligen) så är det nog inte många system som används i sverige som kvalificerar sig på den nivån. Det där med att dina sidor renderas på 2ms när 3 fysiska maskiner är inblandade i en request, är jag lite skeptisk till. Hela din överslagsräkning är uppåt väggarna faktiskt.
Har man sidor som tar flera sekunder att behandla, då kan det vara vettigt att bygga asynkront, ja. Men det där är väl ett annat ämne.
Du måste i så fall implementera asynkron programmering för att få den fördelen du pratar om, det blir ju inte asynkrona requests bara för att du anropar en DLL som ligger på en annan server. Du får bara fördelen att du fördelar ut CPU-lasten men om anropen görs synkront får du precis samma problem att längre requests kan blockar andra när du nått upp till max.
(Och det där med 25 trådar: det går att öka i machine.config, inte alls krångligt, och lämpligt på en modern server med flera CPU:er/CPU-kärnor).
Jo då, jag konstruerar skiktad kod med BLL/DAL i en egen assembly osv,
eftersom det är en bra arkitektur som går att underhålla och återanvända.
Och nej, vi lägger inte all logik i Codebehind (fler personangrepp!)
Systemen är tillräckligt snabba för att hantera den mängd samtidiga requests som kommer in.
Det som man kan gå i taket på ibland är när SQL-databaserna blir jättestora och man har komplex SQL med aggregeringar. Detta brukar vi lösa med bättre SQL, ibland cachning eller andra knep, medans andra köper fler servrar.. :)
Skalbarhet och prestanda är inte samma sak. Men det är två sidor av samma mynt. Om ditt system presterar mycket bra kan det skala, om ditt system presterar dåligt, skalar det också sämre.
Räkna till 10 innan du svarar på inlägget och försök acceptera att man kan ha olika synsätt utan att världen går under... :)Sv: Benchmark?
Och öppnar en ny... jag döper den nya till Prastanda vs Skalbarhet så för vi diskussionen
om sånt där i stället. klart intressant ämne att prata om.
Hoppas ni inte misstycker.
Hum... Stäng funktionen verkar bugga...
Men vi stänger den skriftligt och hoppas ni accepterar det.
Mvh Johan