h0lgerMedlem sedan nov. 2002105 inlägg Jag hade lagt funktionaliteten från DataL och DataAccessL i samma klass och sedan skapat ett nytt lager mellan business och datalager som ärver denna klass.
Business Layer -> Innehåller Valideringar, affärslogik, properties och metoder för objektet. Anropar läs och skriv metoder i Business Data Layer. Inget arv utan rena anrop till BDL.
Business Data Layer -> Innehåller de läs och skriv metoder som krävs för att stödja Business Layer. Finns oftast en per Business Layer. Ärver från Data Access Class
Data Access Class -> En Generic klass som ärvs in i alla Business Data Layers. Innehåller konstruktors för connections, connectionsstrings, GetData, SaveData metoder. Kan ligga i en egen assembly.
Jag lade upp lite exempelkod i denna tråden http://www.webforum.nu/showthread.php?s=&threadid=61409
PMedlem sedan jan. 20012 204 inlägg Har kollat lite på din kod och gjort om min struktur igen....
Som jag förstår så...:
Presentation: presenterar...
DataAccess : Har hand om kopplingen till databasen och metoder så som att returnera dataset, spara/uppdatera/ta bort data etc
Business Data L och Business L :q vad är skillnaden på dessa 2? Förstår inte rikigt vad du menar.....
'------------------------------------------------------'
' Namn: Data.vb '
' Innehåll: databasstruktur '
'------------------------------------------------------'
' Namespacen som importeras
Imports System
Imports System.Xml
Imports System.Data
Imports System.Data.SqlClient
Imports System.Configuration
Namespace Data
Public Class DataAccess ' Basklassen DataAccess Layer
' Connection
Public objCnn As New SqlConnection = (ConfigurationSettings.AppSettings("SqlConnect"))
Function CreateCommand(SqlStatement as String)
Dim SqlCommand as New SqlCommand(SqlStatement,objCnn)
Return SqlCommand
End Function
' Kör en Query mot Databasen
Function RunNonQuery(SqlStatement As String)
try
objCnn.Open()
Dim SqlCommand as SqlCommand =CreateCommand(SqlStatement)
SqlCommand.ExecuteNonQuery()
Catch Exp As SqlException
throw(Exp)
Finally
objCnn.Close()
End Try
End Function
' Returnerar Data i form av ett DatSet
Function GetDataSet(SqlStatement As String)
Try
Dim objDataSet as New DataSet()
objCnn.Open()
Dim objAdapt As New SqlDataAdapter()
objAdapt.SelectCommand = CreateCommand(SqlStatement)
objAdapt.Fill(objDataSet)
Return objDataSet
Catch Exp as SqlException
throw(Exp)
Finally
objCnn.Close()
End Try
End Function
'Returnerar Data i form av en DataReader
Function GetDataReader(SqlStatement as String)
Try
objCnn.Open()
Dim Command As SqlCommand = CreateCommand(SqlStatement)
Dim dr As SqlDataReader = Command.ExecuteReader(CommandBehavior.CloseConnection)
objCnn.Close()
Return dr
Catch Exp as SqlException
throw(Exp)
Finally
objCnn.Close()
End Try
End Function
End Class
Det borde ju inte vara några problem men det är nu det svåra kommer...
Public Class BusinessData ' Business Data Layer
Inherits DataAccess
'Userinfo
Public Function GetUserInfo(Id As String)
Dim strSql String = ("SELECT * FROM tbl_test WHERE id = '"& Id &"' ")
Return GetDataSet(strSql)
End Function
Public Function UpdateUserInfo(Id as String)
Dim strSql String = ("Update tbl_test Set password='test' Where id = '"& Id &"'")
Return RunNonQuery(strSql)
End Function
End Class
Public Class Business ' Business Layer
Public Function GetUserInfo(Id as String)
Dim objtest as New BusinessData()
Dim objDS As DataSet()
objDS = objtest.GetUserInfo(Id)
End Function
End Class
End Namespace
Tänker jag rätt här? Ska ingen data returneras från BusinessLagret??? (verkar vara så i din kod) Hur sköter man då hanteringen från presentationslagret(aspx-filen)?
h0lgerMedlem sedan nov. 2002105 inlägg Du tänker helt rätt dock skall business.GetUserInfo returnera ett dataset eller en xml eller vad du nu vill.
Det kan hända att min kod är fel. Jag torrkodade en del utan kompilering så... :)
PMedlem sedan jan. 20012 204 inlägg okkki.. men vad tjänar man på att dela upp business-lagret i 2 olika delar. Som jag ser det så verkar det bara bli mera jobb. Om man tex vill lägga till en ny funktion så måste man ju både gå in i båda lagren och ändra....
Är den enda fördelen att man slipper ha SQL-kod i Business Lagret och på det sättet får det lättare att ändra koden vid ett eventuellt byte till någon annan databas eller är jag fel ute?
koden ser ju ut tex så här:
Public Class BusinessData ' Business Data Layer
Inherits DataAccess
'Userinfo
Public Function GetUserInfo(Id As String)
Dim strSql As String = ("SELECT * FROM tbl_test WHERE id = '"& Id &"' ")
Return GetDataSet(strSql)
End Function
End Class
Public Class Business ' Business Layer
Public Function GetUserInfo(Id as String)
Dim objtest as BusinessData = New BusinessData()
Return objtest.GetUserInfo(Id)
End Function
End Class
--
Hur bör dessa lager namnges? Framförallt då "Business-lagret"? (såg att du använda några andra namn i din kod...)
PaceMedlem sedan juni 20019 024 inlägg Om man ser till tekniken, var bör lagrerna placeras för att man ska slippa kompilera om ex. SQL-satser?
1. Presentation - aspx
2. Codebehind - vb/cs
3. Affärslogik - dll
4. Data - databas
r) Jag har det i codebehinden för tillfället eftersom de endast behövs användas av en fil, men hur gör man med funktioner som innehåller SQL-strängar som behöver användas av hela webbapplikationen (för att slippa kompilera till dll alltså)?
PMedlem sedan jan. 20012 204 inlägg Varför inte kompilera till dll?
h0lgerMedlem sedan nov. 2002105 inlägg P -> Det kan tyckas vara lite överkurs med ett extra lager men man kan lägga den generella databasklassen och business data lagren i en egen dll och på så sätt slippa kompilera om själva business dll:en om man förändrar databasen. Det kan ju finnas flera olika system som använder sig av denna dll.
Pace -> Jag har sett förslag på lösningar där man har sparat själva sql-satsen och dess parametrar i en xml-fil. Ifrån koden läser man upp dessa. På så sätt slipper man kompilera om dll.
Men det som är ännu bättre är att använda lagrade procedurer i databasen.
PMedlem sedan jan. 20012 204 inlägg Jo... lagrade procedurer få bli ett senare steg. Om det funkar som det ska så borde det ju inte vara svårt att "uppgradera".
Sista frågan: Jag håller på med en grej för att kontrollera om man är behörig för att utföra ngt. Jag skickar in lite uppgifter och får ut ett DataSet. I detta lager finns det en kolumn som anger om man är behörig. Är det smartast att kontrollera detta BusinessDL/BusinessL och sedan returnera TRUE/FALSE eller ska denna kontroll ske i Presentationslagret :q
h0lgerMedlem sedan nov. 2002105 inlägg Vad kontrollerar behörigheten? Är det på sidnivå du vill göra din kontroll? Alltså, har denna användaren rätt att se den efterfrågade sidan? Eller har du andra behörigheter du också vill kontrollera?
nikoMedlem sedan juni 20022 599 inlägg
P skrev:
Är det smartast att kontrollera detta BusinessDL/BusinessL och sedan returnera TRUE/FALSE eller ska denna kontroll ske i Presentationslagret
Nu har jag inte läst hela tråden men ..
Generellt kan man säga att i .NET så ska inte komponenter "svälja" fel och returnera någon form av status. Istället ska komponter låta exceptions fortplanta sig uppåt och låta "huvudapplikationen" på egen hand avgöra hur felet ska hanteras. Eventuellt så kan komponenten "paketera om" felet och kasta det på nytt. I ditt fall skulle jag rekomendera att komponenterna skapar ett eget SecurityException-objekt och sen kastar detta uppåt med "throw".
PMedlem sedan jan. 20012 204 inlägg behörigheten kontrollerars av om en kolumn i tabellen är true eller false för den aktuelle användaren, id:t som parameter i funktionen.
Om den är true så ska han ha tillgång till sidan.
Så antingen returnerar jag ett DataSet med informationen från från tabellen och kontrollerar det på det aktuella sidan eller också så gör jag kontrollen i funktionen som returnerar DataSetet men returnerar då istället (true/false) beroende på om han ska kunna se sidan.(hmm då måste jag ju kontrollera det igen på sidan :/).. Båda sätten fungerar ju men frågan är vilket som är "bäst"
För att röra till det lite mer så har jag en 10-15 sidor som behörigheten ska kontrolleras på, men då olika kolumner i tabellen. Alltså man kan vara behörig för en sida men inte för en annan.
Då har jag tänkt att göra en huvudsida med olika länkar som är klickbara eller inte. Men om man vet vad sidan heter så kan man ju komma dit ändå och då måste det kontrolleras på den aktuella sidan.
---
niko: Skumläste ditt inlägg och fattar inte mycket... jaja åker iväg ett par timmar i friska luften nu. När jag kommer tillbaka så är hjärnan laddad!
PatrikBMedlem sedan mars 20002 836 inlägg
Men det som är ännu bättre är att använda lagrade procedurer i databasen.
Finns nog en hel del som inte kör MS-SQL Server utan kör mySQL som dbms. Då blir man mer eller mindre "tvingad" att kompilera sina sql-frågor inne i BDL (som egen dll) eller spara dessa i ngn typ av xml-fil som sqlfrågorna kan sparas i.
Pace:
CodeBehind filen vill jag säga tillhör PL då den är helt bunden till aspx-filen. I den ska inga sql-frågor alls finnas.
Nu är ju jag ingen expert i ämnet OOP men det jag har läst/sett bör man som h0lger säger skapa en BL dll och sedan en BDL dll. I BDL lägger man sql-frågor, sp-namn etc.
Själv brukar jag i min BDL skapa datareaders som bygger upp olika collections som returneras till BL.
h0lger:
Har sett många lösningar där man från BL "bubblar ned" ett objekt till BDL. Enligt mig funkar det rätt bra ... men, BL och BDL blir ju rätt knutna till varandra, fast, varje lager är knutna till det ena lagret på ett eller annat sätt, även de exempel som du har visat. Beroendet som jag ser är att lagret till vänster måste vet lite om lagret närmast till höger i denna kedja:
PL --> BL --> BDL --> DL
cya,
PatrikB
h0lgerMedlem sedan nov. 2002105 inlägg P-> Jag skulle rekommendera dig att göra en httpmodule som kontrollerar att användaren har rättigheter innan sidan bearbetas. Då bör du skapa ett egen definierat exception som tar hand om felet och bubblar upp detta till modulen.
PatrikB -> har också sett dessa typer av nedbubblingar men är inte riktigt nöjd med dem. Vill att det skall finnas så lite beroenden som möjligt. Ser hellre att varje lager är som en svart låda där man skickar in och returnerar så generella datatyper som möjligt. Håller med dig i ditt inlägg i övrigt.
PaceMedlem sedan juni 20019 024 inlägg
h0lger skrev:
Pace -> Jag har sett förslag på lösningar där man har sparat själva sql-satsen och dess parametrar i en xml-fil. Ifrån koden läser man upp dessa. På så sätt slipper man kompilera om dll.
Ska ha det i åtanke i framtiden! Dock måste man ju lägga dem utanför webrooten så att de inte kan läsas av utomstående...
PatrikB skrev:
Pace:
CodeBehind filen vill jag säga tillhör PL då den är helt bunden till aspx-filen. I den ska inga sql-frågor alls finnas.
Nu är ju jag ingen expert i ämnet OOP men det jag har läst/sett bör man som h0lger säger skapa en BL dll och sedan en BDL dll. I BDL lägger man sql-frågor, sp-namn etc.
Själv brukar jag i min BDL skapa datareaders som bygger upp olika collections som returneras till BL.
BL hit och BDL dit. Vad hände med svenskan? ;)
Eftersom min utdata är bunden till aspx-sidan så kör jag med mina sql-satser i codebehind-filen tills vidare. Och av rent praktiska skäl.
PMedlem sedan jan. 20012 204 inlägg
h0lger skrev:
P-> Jag skulle rekommendera dig att göra en httpmodule som kontrollerar att användaren har rättigheter innan sidan bearbetas. Då bör du skapa ett egen definierat exception som tar hand om felet och bubblar upp detta till modulen.
Det verkar aningen för svårt för mig... står inget om httpmoduler i min asp.net bok av Jesper Ek ;)
Läste tidigare att BL "Innehåller Valideringar, affärslogik, properties och metoder för objektet" Ingår det i detta att BL utför uträkningar och kontrollerar Data från BDL eller ska allt detta skötas av PL?
Svenskan är död! Snart kommer all kommunication ske på Engelska!
PatrikBMedlem sedan mars 20002 836 inlägg Det ska skötas av BL (Affärslagret) ej PL (Presentationslagret)
Svenska översättningar/böcker tenderar till att komma ett bra tag senare än de engelska. Så, engelskan är programmerarens språk :e
cya,
PatrikB
PMedlem sedan jan. 20012 204 inlägg Vad kallar ni erat BussinessLager? Känns konstigt att anropa "Business"...
h0lgerMedlem sedan nov. 2002105 inlägg PatrikBMedlem sedan mars 20002 836 inlägg
h0lger skrev:
Ser hellre att varje lager är som en svart låda där man skickar in och returnerar så generella datatyper som möjligt
Generella för vem? för dig och ditt team, eller för alla andra?
En applikation består ju oftast av flera olika objekt som samverkar. Som utvecklare bygger man ju upp en massa olika egna objekt som för mig som utvecklare blir "generella". Dessa "verktyg" (objekt) kommer att tillhöra MIN (teamets) "verktygslåda".
Du ser ju detta användas i NET Frameworkets std klasser tex:
Dim myConn As New SqlConnection("connection string")
Dim strSQLlist As String = "sproc_getListOfAllProductsByCategoryId"
Dim myCommand As New SqlCommand(strSQLlist, [b]myConn[/b])
.
.
.
etc
Där tar ju SqlCommand emot två inparametrar. En generell datatyp string och ett objekt. SqlConnection har således blivit en generell datatyp. Således bör ju även mina objekt bli generella. Inte för dig eller för någon annan, utan just för mig och mitt team.
Så enligt mig så är det inte fel att bubbla upp eller ned ett objekt eftersom för mig är det en generell datatyp.
Hoppas att du hängde med i mitt "tankesätt" :e
cya,
PatrikB
h0lgerMedlem sedan nov. 2002105 inlägg Jag hänger med i ditt resonemang. Dock ser jag fördelar med att man ifrån presentationslagret arbetar med mer generella datatyper. Egentligen borde man enbart returnera ren xml till presentationslagret, detta för att underlätta vid byte av klienter etc.
Nu är mitt resonemang på en teoretisk nivå. Om man bygger en mindre applikation där omgivningen är given tycker jag att detta är överkurs.