24. februar 2006 - 13:52Der er
53 kommentarer og 2 løsninger
arrylist i forbindelse med mit buisness lag
Jeg opbygger typisk mine moduler efter princippet UI, BLL, DAL altså i 3 lag og nogle gange flere.
Mit spørgsmål går på om det er ok at kalde mit BLL i mit DAL for at lave en arryliste på følgende Måde :
..... Dim objList As ArrayList While Dr.Read Dim BLL As MitNamespace.MitBuisnessLag = New MitNamespace.MitBuisnessLag BLL.Id = Convet.ToInt32(Dr("Id")) BLL.Name = Convet.String(Dr("Name")) BLL.Email = Convet.String(Dr("Email")) objList.Add(BLL) End While .....
Herefter retunere jeg arrylisten og kan så benytte den til f.eks. at smide i en dataliste eller datagrid, men er det ok at gøre det på denne måde eller skal jeg gøre det anderledes når jeg smidder det ud som en arraylist ?
Det var mere for at høre om jeg skal forsøge at holde det helt adskilt og så gøre det på en anden måde, men hvis du mener det er ok så gør jeg ikke mere ved det.
Private Function MitBuisnessLag(ByVal name As String, ByVal id As Integer, ByVal email As String) As Public 'sæt property værdier her End Function
så tror jeg du skal bruge det på denne måde
Dim BLL As MitNamespace.MitBuisnessLag = New MitNamespace.MitBuisnessLag(Convet.String(Dr("Name")),Convet.ToInt32(Dr("Id")),Convet.String(Dr("Email")))
Normalt laver jeg jo bare 2 en default og en med id :
Public Sub New() Id = 0 Name = "" Email = "" End Sub
Public Sub New(ByVal id As Integer) Id = _Id Name = _Name Email = _Email End Sub
Og så kalder den fra mit UI med følgende :
'--- Hvis jeg vil oprette en ny record. Dim objBLL as Namespace.BLL = New Namespace.BLL() objBLL.Name = Textbox1.Text objBLL.Email = Textbox2.Text objBLL.Create()
Eller :
'--- Hvis jeg vil hente, redigere el. slette en record. Dim objBLL as Namespace.BLL = New Namespace.BLL(Request.QueryString("id")) objBLL.Name = "Skift navn" objBLL.Email = "Skift email" objBLL.Edit()
Og så er det så at jeg ikke helt kan se hvorledes jeg skal hente alle records i databasen.
det jeg lavede var bare en måde at gøre Dim objList As ArrayList While Dr.Read Dim BLL As MitNamespace.MitBuisnessLag = New MitNamespace.MitBuisnessLag BLL.Id = Convet.ToInt32(Dr("Id")) BLL.Name = Convet.String(Dr("Name")) BLL.Email = Convet.String(Dr("Email")) objList.Add(BLL) End While
For at du kan følge min tankegang så har jeg noget der ligner :
BLL :
Function Create() '--- Noget kode der validere data inden de sendes videre End Function
Function Edit() '--- Noget kode der validere data inden de sendes videre End Function
Function Delete() '--- Noget kode der validere data inden de sendes videre End Function
Her skal jeg jo så også have en function der tager sig af den arrayliste jeg sender videre fra mit DAL, men jeg kan ikke helt se hvorledes jeg skal få den videre fra min BLL ???
Arraylisten bliver lavet i mit DAL i en metode der trækker data fra databasen og ligger det over i en arrayliste :
Public Function FindAll() '--- Noget kode der laver database forbindelse og sql command Dim objList As ArrayList While Dr.Read Dim BLL As MitNamespace.MitBuisnessLag = New MitNamespace.MitBuisnessLag BLL.Id = Convet.ToInt32(Dr("Id")) BLL.Name = Convet.String(Dr("Name")) BLL.Email = Convet.String(Dr("Email")) objList.Add(BLL) End While Return objList End Function
kan du ikke bare i det tilfælde at du skal have data gemt i database løbe alle rækkerne i arraylisten igennem og sende de enkelte objekter ned igennem lagene ?
Jeg skal ikke have gemt dataene jeg skal hente alt og derfra liste dem i et datagrid el. dataliste så jeg skal som bare lave en Select * From Tabel Order By Id og så fyrre det hele i et arraylist så jeg har det til at smide det hovedet på brugeren.
DTO klasser brugt mellem BLL og DAL boer ligge i DAL
DAL kode boer ikke kalde metoder i BLL - kun inddirekte gennem noget publish-subscribe/observer pattern og selv i dette tilfaelde kender DAL kun et interface som er i DAL
paa den maade afhaenger DAL ikke af BLL
hvilket baade giver det paeneste design og nemmeste build
med hensyn til constructor vil jeg godt reklamere lidt for at lade dem kalde hinanden:
public class A { private string s; public A() : this("") { } public A(string s) { this.s = s; } public string S { get { return s; } set { s = value; } } public override string ToString() { return s; } }
Public Class A Private _s As String Public Sub New() MyClass.New("") End Sub Public Sub New(ByVal s As String) _s = s End Sub Public Property S() As String Get Return _s End Get Set _s = value End Set End Property Public Overloads Overrides Function ToString() As String Return s End Function End Class
public class B { private const string DEF_S = ""; private string s; public B() : this(DEF_S) { } public B(string s) { this.s = s; } public string S { get { return s; } set { s = value; } } public override string ToString() { return s; } }
Public Class B Private Const DEF_S As String = "" Private _s As String Public Sub New() MyClass.New(DEF_S) End Sub Public Sub New(ByVal s As String) _s = s End Sub Public Property S() As String Get Return _s End Get Set _s = value End Set End Property Public Overloads Overrides Function ToString() As String Return s End Function End Class
Og nu tabte jeg så tråden lidt. Jeg har prøvet at lave et simpelt eksempel på hvordan jeg ville lave det kan i så ikke prøve at kigge på det og komme med forslag til hvorledes i mener det skal være ?
For at gøre det lidt overskueligt har jeg kun lavet en create og findall metode.
Min DAL klasse :
Imports System Imports System.Data Imports System.Data.SqlClient Imports System.Collections
Namespace Newsletter Public Interface INewsletterData Function CreateNew(ByVal Name As String, _ ByVal Email As String) As Integer Function FindAll() As ArrayList End Interface
Public Class DAL Implements INewsletterData Dim objDb As DbClass = New DbClass
Public Function CreateNew(ByVal Name As String, _ ByVal Email As String) As Integer Implements INewsletterData.CreateNew Dim objConn As SqlConnection = objDb.SqlConnect Dim objComm As New SqlCommand("Insert Into tbl_newsletter (Name, Email) values (@Name, @Email)", objConn) objComm.Parameters.Add("@Name", SqlDbType.NVarChar) objComm.Parameters.Add("@Email", SqlDbType.NVarChar) objComm.Parameters("@Name").Value = Name objComm.Parameters("@Email").Value = Email objComm.ExecuteNonQuery() objComm.Parameters.Clear() '--- Henter ideet fra den netop oprettede record. objComm.CommandText = "Select @@Identity" Dim intReturn As Integer = Convert.ToInt32(objComm.ExecuteScalar) objDb.SqlClose() '--- Retunere det nye id Return intReturn End Function
Public Function FindAll() As System.Collections.ArrayList Implements INewsletterData.FindAll Dim objConn As SqlConnection = objDb.SqlConnect Dim objComm As New SqlCommand("Select * From tbl_newsletter Order By Id Desc", objConn) Dim Dr As SqlDataReader = objComm.ExecuteReader Dim objList As ArrayList While Dr.Read Dim objBLL As Newsletter.BLL = New Newsletter.BLL objBLL.Id = Convert.ToInt32(Dr("Id")) objBLL.Name = Convert.ToString(Dr("Name")) objBLL.Email = Convert.ToString(Dr("Email")) objList.Add(objBLL) End While Dr.Close() objDb.SqlClose() Return objList End Function End Class End Namespace
Og min BLL klasse :
Namespace Newsletter Public Class BLL Dim objDAL As INewsletterData = New Newsletter.DAL
Private _Id As Integer Private _Name As String Private _Email As String
Public Property Id() As Integer Get Return _Id End Get Set(ByVal Value As Integer) _Id = Value End Set End Property
Public Property Name() As String Get Return _Id End Get Set(ByVal Value As String) _Id = Value End Set End Property
Public Property Email() As String Get Return _Id End Get Set(ByVal Value As String) _Id = Value End Set End Property
Public Sub New() _Id = 0 _Name = "" _Email = "" End Sub
Public Sub New(ByVal intId As Integer) _Id = intId _Name = Name _Email = Email End Sub
Public Function Create() As Integer '--- her kommer noget koder der tjekker navn og email '--- inden de sendes videre til lagring i database. Dim intReturn As Integer intReturn = objDAL.CreateNew(_Name, _ _Email) Return intReturn End Function
Public Function GetAll() As ArrayList '--- Laver cache af arraylist Dim Source As ArrayList = CType(HttpContext.Current.Cache("Newsletter"), ArrayList) If Source Is Nothing Then Source = objDAL.FindAll() HttpContext.Current.Cache("Newsletter") = Source Else HttpContext.Current.Cache("Newsletter") = Source End If Return Source End Function End Class End Namespace
Så kan jeg f.eks. bruge det i mit UI med noget i denne stil :
Dim objBLL As Newsletter.BLL = New Newsletter.BLL objBLL.Name = Textbox1.Text objBLL.Email = Textbox1.Text objBLL.Create()
Eller hvis jeg ville hente og vise :
If Not IsPostBack Then DataList1.DataSource = objBLL.GetAll() DataList1.DataBind() End If
Men det lyder ikke til at det helt er den måde du mener er bedst arne_v ?
Hvad er det der ikke er BL over den jeg har lavet ?
Hvad mener du med at jeg skal lade CreateNew bruges som argument ?
Og sidst men ikke mindst hvis jeg skal lave en ny BLL med DAL referencen + Create + GetAll så er der da ikke meget forskel på det andet end at mine properties og sub new bliver flyttet til DAL klassen ?
Kunne du så ikke prøve at sætte det hele sammen ud fra det du mener så jeg har en sammenhæng i det hele bare ud fra de klasser jeg har lavet ovenfor ?
Jeg ved godt at min BLL er tynd som den er nu men der kommer validering, kryptering, beregninger osv. osv. osv...... i den del, det var bare for at holde det simpelt her og nu ;o)
Jeg har været ved at sidde og læse lidt på en artikel jeg fandt på nettet i dag hvor man benytter sig af en "DataHelper" klasse. Den øvrige opdeling ser ud som følger :
DataHelper.vb klasse = Nogle faste metoder som generalt tager sig af behandling i databasen Data.vb klasse = som sender sql-sætning og parametre videre til DataHelper.vb klassen Buisness.vb klasse = som modtager indput fra brugerfladen og sender dem videre til Data.vb klasse Info.vb = som indeholder de properties der skal benyttes til en given application
Så har jeg prøvet at sætte det sammen med lidt kode af det ovenfor så jeg får følgende klasser :
Private _ConnectionString As String Public Sub New() _ConnectionString = ConfigurationSettings.AppSettings("connectionstring") End Sub
Public Function ExecuteNonQuery(ByVal Sql As String, _ ByVal Param() As SqlParameter) As Integer Dim objConn As New SqlConnection(_ConnectionString) Dim objComm As New SqlCommand(Sql, objConn) For i As Integer = 0 To Param.Length - 1 objComm.Parameters.Add(Param(i)) Next objConn.Open() Dim intReturn As Integer = objComm.ExecuteNonQuery() objConn.Close() Return intReturn End Function
Public Function ExecuteDataSet(ByVal Sql As String) As DataSet Dim ds As New DataSet Dim da As New SqlDataAdapter(Sql, _ConnectionString) da.Fill(ds) Return ds End Function
Public Function ExecuteScalar(ByVal Sql As String, _ ByVal Param() As SqlParameter) As Object Dim objConn As New SqlConnection(_ConnectionString) Dim objComm As New SqlCommand(Sql, objConn) For i As Integer = 0 To Param.Length - 1 objComm.Parameters.Add(Param(i)) Next objConn.Open() Dim retval As Object = objComm.ExecuteScalar objConn.Close() Return retval End Function
Public Function ExecuteDataSet(ByVal Sql As String, _ ByVal Param() As SqlParameter) As DataSet Dim ds As New DataSet Dim da As New SqlDataAdapter(Sql, _ConnectionString) For i As Integer = 0 To Param.Length - 1 da.SelectCommand.Parameters.Add(Param(i)) Next da.Fill(ds) Return ds End Function End Class End Namespace
'####################################################################### '--- Data klassen '####################################################################### Imports System Imports System.Data Imports System.Data.SqlClient
Namespace Newsletter Public Interface INewsletterData Function CreateNew(ByVal Info As Newsletter.Info) As Integer Function FindAll() As DataSet End Interface
Public Class Data Implements INewsletterData Dim DataHelp As Newsletter.DataHelper = New Newsletter.DataHelper
Public Function CreateNew(ByVal Info As Newsletter.Info) As Integer Implements INewsletterData.CreateNew Dim Sql As String = "Insert Into tbl_newsletter (Name, Email) values (@Name, @Email)" Dim Param(1) As SqlParameter Param(0) = New SqlParameter("@Name", Info.Name) Param(1) = New SqlParameter("@Email", Info.Email) Dim intReturn As Integer = DataHelp.ExecuteNonquery(Sql, Param) '--- Retunere det nye id Return intReturn End Function
Public Function FindAll() As DataSet Implements INewsletterData.FindAll Dim Sql As String = "Select * From tbl_newsletter Order By Id Desc" Dim dsReturn As DataSet = DataHelp.ExecuteDataSet(Sql) Return dsReturn End Function End Class End Namespace
'####################################################################### '--- Buisness klassen '####################################################################### Namespace Newsletter Public Class Buisness Dim objData As INewsletterData = New Newsletter.Data
Public Function Create(ByVal Info As Newsletter.Info) As Integer '--- her kommer noget koder der tjekker navn og email '--- inden de sendes videre til lagring i database. Dim intReturn As Integer intReturn = objData.CreateNew(Info) Return intReturn End Function
Public Function GetAll() As DataSet '--- Laver cache af dataset Dim Source As DataSet = CType(HttpContext.Current.Cache("Newsletter"), DataSet) If Source Is Nothing Then Source = objData.FindAll() HttpContext.Current.Cache("Newsletter") = Source Else HttpContext.Current.Cache("Newsletter") = Source End If Return Source End Function End Class End Namespace
'####################################################################### '--- Info klassen '####################################################################### Namespace Newsletter Public Class Info Private _Id As Integer Private _Name As String Private _Email As String
Public Property Id() As Integer Get Return _Id End Get Set(ByVal Value As Integer) _Id = Value End Set End Property
Public Property Name() As String Get Return _Id End Get Set(ByVal Value As String) _Id = Value End Set End Property
Public Property Email() As String Get Return _Id End Get Set(ByVal Value As String) _Id = Value End Set End Property End Class End Namespace
Hvis du har tiden til må du gerne kigge disse igennem og se om ikke det er noget hen af det du har skrevet om tidligere ?
Imports System Imports System.Data Imports System.Data.SqlClient Imports System.Collections
Namespace NewsletterDAL Public Class Newsletter Private _Id As Integer Private _Name As String Private _Email As String Public Property Id() As Integer Get Return _Id End Get Set(ByVal Value As Integer) _Id = Value End Set End Property
Public Property Name() As String Get Return _Name End Get Set(ByVal Value As String) _Name = Value End Set End Property
Public Property Email() As String Get Return _Email End Get Set(ByVal Value As String) _Email = Value End Set End Property Public Sub New() Call MyClass.New(0, "", "") End Sub Public Sub New(ByVal Id As Integer, ByVal Name As String, ByVal Email As String) _Id = Id _Name = Name _Email = Email End Sub End Class
Public Interface INewsletterDb Function CreateNew(ByVal News As Newsletter) As Integer Function FindAll() As ArrayList End Interface
Public Class NewsletterSql Implements INewsletterDb Dim objDb As DbClass = New DbClass Public Function CreateNew(ByVal News As Newsletter) As Integer Implements INewsletterDb.CreateNew Dim objConn As SqlConnection = objDb.SqlConnect Dim objComm As New SqlCommand("Insert Into tbl_newsletter (Name, Email) values (@Name, @Email)", objConn) objComm.Parameters.Add("@Name", SqlDbType.NVarChar) objComm.Parameters.Add("@Email", SqlDbType.NVarChar) objComm.Parameters("@Name").Value = News.Name objComm.Parameters("@Email").Value = News.Email objComm.ExecuteNonQuery() objComm.Parameters.Clear() '--- Henter ideet fra den netop oprettede record. objComm.CommandText = "Select @@Identity" Dim id As Integer = Convert.ToInt32(objComm.ExecuteScalar) objDb.SqlClose() '--- Retunere det nye id Return id End Function Public Function FindAll() As ArrayList Implements INewsletterDb.FindAll Dim objConn As SqlConnection = objDb.SqlConnect Dim objComm As New SqlCommand("Select * From tbl_newsletter Order By Id Desc", objConn) Dim Dr As SqlDataReader = objComm.ExecuteReader Dim objList As ArrayList While Dr.Read Dim objBLL As NewsletterDAL.Newsletter = New NewsletterDAL.Newsletter objBLL.Id = Convert.ToInt32(Dr("Id")) objBLL.Name = Convert.ToString(Dr("Name")) objBLL.Email = Convert.ToString(Dr("Email")) objList.Add(objBLL) End While Dr.Close() objDb.SqlClose() Return objList End Function End Class End Namespace
Namespace NewsletterBLL Public Class NewsletterManager Dim objDAL As NewsletterDAL.INewsletterDb = New NewsletterDAL.NewsletterSql Public Function CreateNew(ByVal Name As String, ByVal Email As String) As Integer '--- her kommer noget koder der tjekker navn og email '--- inden de sendes videre til lagring i database. Dim id As Integer id = objDAL.CreateNew(New NewsletterDAL.Newsletter(0, Name, Email)) Return id End Function Public Function GetAll() As ArrayList '--- Laver cache af arraylist Dim Source As ArrayList = CType(HttpContext.Current.Cache("Newsletter"), ArrayList) If Source Is Nothing Then Source = objDAL.FindAll() HttpContext.Current.Cache("Newsletter") = Source Else HttpContext.Current.Cache("Newsletter") = Source End If Return Source End Function End Class End Namespace
1. Du laver 2 namespaces NewsletterDAL og NewsletterBLL, hvorfor ikke beholde dem i det samme namespace ?
2. Du mener også at de skal ligge i 2 Dll'er, men når jeg køre siden laves der jo automatisk kun 1 Dll så det kan jeg ikke helt følge dig i.
3. Mine Create, Update og Delete functioner kommer naturligt vis til at slette cachen da den jo ellers ikke længere er "up to date"
4. Hvor i koden er det du ikke er tilfreds med Id håndteringen ?
Ellers ser det fornuftigt ud det du har lavet.
Med hensyn til den artikel jeg har læst om DAAB måden at gøre det på, syntes jeg som sådan er ok, dog er jeg også selv til collection da jeg mener at dette er en hurtigere måde at præsentere data på. Jeg syntes dog at der ville være en del mindre kode at skulle skrive da database hjælper klassen jo kun skal skrives en gang og efterfølgende ikke skal skrive så meget kode i mine Create, Update og Delete metoder, men som du selv skriver er det jo en smags sag.
En anden ting er at der vel ikke er noget i vejen for at ligge Properties ud i an klasse fil for sig, på den måde har jeg adgang til dem fra PL uden at skulle loade hele DAL namespacet ?
Og her syntes jeg så at det bliver lettere at håndtere Id som du skriver ovenfor.
De ligger jo i en klasse og den skal de ikke ud af, det var mere om ikke det var smart at have klassen "Newsletter" fra din kode liggende i sit eget namespace "NewsletterInfo" så er der tilgang til dem uden at skulle loade hele "NewsletterDAL" namespacet, det virker for mere logisk ?
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.