lighterus>> det er ikke lige så ofte jeg får taget mig tid til at lave noget i asp.net :( udover her på eksperten. Al min tid går med at kode et winformprogram i c#... men hvad... meningen var da at få portet det til asp.net engang, så der skulle der være rig mulighed for at lege med det igen :)
uhm... din property ser god nok ud... tror jeg nok, jeg er ikke så hård i vb.net-syntaksen dog skal sætte txtCompanyValue til noget og ikke TextBox1, da den jo er private...
meeen.. jeg har dog lige set en stor fejl du har lavet... du skal ikke skrive UserManagement.txtCompanyValue med updateUser.txtCompanyValue da det jo er objectet du skal referere til og ikke klassen (det er kun når ens metoder/properties er shared man kan referere til klassen). Og når det er sagt, tror du ikke du skulle tage og læse nogle tutorials? der er nogle gode på www.gotdotnet.com
Jeg tjekker de tutorials ud der. Men bare fordi jeg ikke lige har brugt properties før cyberfessor! Altså......... ;-) hehe
Lige 2 ting:
Hvorfor skulle man kunne refere til en klasse? >> (det er kun når ens metoder/properties er shared man kan referere til klassen) i stedet for objektet?
Og hvis jeg laver den der Textbox1 der til en Public string, er den så som den skal være?
SÅdan her:
Public TextBox1 As String
Public Property txtCompanyValue() As String Get txtCompanyValue = TextBox1 End Get Set(ByVal Value As String) TextBox1 = Value End Set End Property
Og:
Dim updateUser As UserManagement = New UserManagement() updateUser.txtCompanyValue = txtCompany.Text
det tager tid at oprette et object i hukommelsen så nogen gange kan det være en fordel at lave en funktion shared. På den måde behøver man ikke nogen reference til et object. Du tænker nok ikke over det, men når du f.eks. skriver int.Parse eller Math.Rnd så tilgår du metoderne Parse og Rnd i klasserne int og Math... og i og med at de metoder er shared, så behøver du ikke at skrive f.eks.
Dim i As int = new int() i.Parse
ang. den kode du har skrevet til sidst i din kommentar, så ser den rigtig ud :)
Men hvad så hvis det er en Output parameter fra en SPROC?
hvordan initialisere jeg den så?
Det kode her er fra min funktion i UserUpdate klassen:
Public ReadOnly Property OutPut1Value() As String Get OutPut1Value = OutPut1 End Get End Property
'output Dim parameterOutput As New SqlParameter("@Result", SqlDbType.Int, 4) myCommand.Parameters.Add(parameterOutput) parameterOutput.Direction = ParameterDirection.Output
Nej......... den output SPROC parameter er for at tjekke om der er fejl under opdateringen. Har lavet en Transaction.
> 0 = ingen fejl,
0 = fejl
-1 = fejl
Før så min kode sådan her ud:
Dim intResult As Integer = CInt(myCommand.Parameters("@Result").Value) Dim strResult As String = "Resultat=" & CStr(intResult) & "<br /><br />" '** udskriver resultatet -1, 0 eller 1 **
'select case ud fra en af disse 'output parametre: -1, 0 eller 1 Select Case intResult Case -1 : strResult += "<font style=""color:red;"">Der skete en fejl, og ingen brugerdata er blevet opdateret!</font>"
Case 0 : strResult += "<font style=""color:red;"">Der skete en fejl, og ingen brugerdata er blevet opdateret!</font>"
Case Is > 0 : strResult += "<font style=""color:green;"">Bruger dataene blev opdaterede korrekt!</font>" End Select
Men jeg kan jo ikke bruge dennne her mere:
Dim intResult As Integer = CInt(myCommand.Parameters("@Result").Value) ´da det ligger i min funktion i klassen.
Dim intResult As Integer = CInt(updateUser.OutPut1Value) Dim strResult As String = "Resultat=" & CStr(intResult) & "<br /><br />" '** udskriver resultatet -1, 0 eller 1 **
'select case ud fra en af disse 'output parametre: -1, 0 eller 1 Select Case intResult Case -1 : strResult += "<font style=""color:red;"">Der skete en fejl, og ingen brugerdata er blevet opdateret!</font>"
Case 0 : strResult += "<font style=""color:red;"">Der skete en fejl, og ingen brugerdata er blevet opdateret!</font>"
Case Is > 0 : strResult += "<font style=""color:green;"">Bruger dataene blev opdaterede korrekt!</font>" End Select
disco_keld>> hehe... rolig nu... asp.net er altså ikke svaret på alle verdens problemer. I teorien kan du ikke lave noget i asp.net som du ikke kan i asp, eller php for den sags skyld. dog er man som udvikler rimelig godt stillet med det framework og måden sin kode bliver kørt på med asp.net, som gør det utrolig nemt at skrive effektiv, ren og overskuelig og kode som er nem at genbruge :)
Det eneste jeg er i tvivl om er om min metode "AddNewUser" skal returnere et Integer i stedet for objektet "CreateNewUser".
Vil du ikke lige vise mig hvordan?
Plus den label der, der ligger i samme metode også. Den ved jeg heller ikke hvordan jeg skal omkode, så jeg kan tilgå den fra min code-behind class.
Her er min Usermanagement class: ----------------------------------------------------------------- Imports System Imports System.Web Imports System.Web.UI Imports System.Web.UI.WebControls Imports System.Data Imports System.Data.SqlClient Imports System.Data.SqlTypes Imports System.Reflection Imports SecurityLib
Public Class CreateNewUser Public TextBox1 As String Public TextBox2 As String Public TextBox3 As String Public TextBox4 As String Public DropList As Integer Public OutPut As Integer End Class
Public Class UserManagement Inherits DbClass
'tilføj en ny bruger Public Function AddNewUser(ByVal ddlUserRightsValue As Integer, ByVal txtCompanyValue As String, ByVal txtUserNameValue As String, ByVal txtEmailValue As String, ByVal txtPasswordValue As String) As CreateNewUser Dim con As New SqlConnection(connectionString)
Dim cmd As New SqlCommand("sp_GetUserLoginSpecs", con) 'cmd.CommandType = CommandType.StoredProcedure
'parameter til et email tjek længere nede 'cmd.Parameters.Add("@Email", SqlDbType.NVarChar, 50).Value = txtEmailValue
Try 'åbner conn til Db If con.State <> ConnectionState.Open Then con.Open() End If
'tjekker om email adressen allerede findes i Db 'Dim reader As SqlDataReader = cmd.ExecuteReader() 'If reader.Read = True Then 'blblMsg.Text = "<ul><li>Der findes allerede en bruger med denne email-adresse!</li></ul>" 'blblMsg.ForeColor = Color.Red 'blblMsg.Font.Bold = False 'con.Dispose() 'con.Close() 'Exit Try 'Else 'reader.Close()
'Tilføj bruger i Db tabel User_Accounts cmd = New SqlCommand("sp_UserAdd", con) cmd.CommandType = CommandType.StoredProcedure
'input parametre til tilføjelse af det nye bruger data cmd.Parameters.Add("@Company", SqlDbType.NVarChar, 50).Value = txtCompanyValue
cmd.ExecuteNonQuery() 'End If Catch Throw Finally If con.State <> ConnectionState.Closed Then con.Dispose() con.Close() End If End Try
Dim addUser As New CreateNewUser() addUser.TextBox1 = cmd.Parameters("@Company").Value.ToString() addUser.TextBox2 = cmd.Parameters("@Name").Value.ToString() addUser.TextBox3 = cmd.Parameters("@Email").Value.ToString() addUser.TextBox4 = cmd.Parameters("@Password").Value.ToString() addUser.DropList = CType(cmd.Parameters("@UserRights").Value, Integer) addUser.OutPut = CType(cmd.Parameters("@Result").Value, Integer)
Return addUser End Function
End Class ------------------------------------------------------------------------------
Og her kommer min code-behind class:
Public Sub btnNewUser_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNewUser.Click If IsValid Then If CInt(Context.Session("TP_UserRights")) <> 1 Then With blblError .Text = "<ul><li>Du har ikke rettigheder til at tilføje data i databasen!</li></ul>" .ForeColor = Color.Red .Visible = True End With Else Dim txtCompanyValue As String = bTxtCompany.Text Dim txtUserNameValue As String = bTxtUserName.Text Dim txtEmailValue As String = bTxtEmail.Text Dim txtPasswordValue As String = bTxtPassword.Text Dim ddlUserRightsValue As Integer = CType(bDdlUserRights.SelectedItem.Value, Integer)
Dim userManagement As UserManagement = New UserManagement() Dim createNewUser As CreateNewUser = New CreateNewUser() createNewUser = userManagement.AddNewUser(ddlUserRightsValue, txtCompanyValue, txtUserNameValue, txtEmailValue, txtPasswordValue) 'fanger værdien af output parameteren fra @Result
Dim intResult As Integer = createNewUser.OutPut Dim strResult As String '= "Resultat=" & CStr(intResult) & "<br /><br />" '** udskriver resultatet -1, 0 eller 1 **
'select case ud fra en af disse 'output parametre: -1, 0 eller 1 Select Case intResult Case -1 : strResult += "<font style=""color:red;"">Der skete en fejl, og ingen brugerdata er blevet tilføjet!</font>"
Case 0 : strResult += "<font style=""color:red;"">Der skete en fejl, og ingen brugerdata er blevet tilføjet!</font>"
Case Is > 0 : strResult += "<font style=""color:green;"">Bruger dataene blev tilføjet korrekt!</font>" End Select
'sætter Session til UserRights fra Db, til senere brug. 'ellers ville den være 0 Dim userRights As Integer userRights = Convert.ToInt32(Context.Session("TP_UserRights"))
nu ved jeg jo ikke ikke hvordan dit site er bygget op, dog ser det nogenlunde ok ud... en ting jeg dog ikek forstår, og det er hvad du skal bruge CreateNewUser-klassen til ?!?!?! jeg mener, du returnerer en instans af den klasse, men bruger den ikke til noget, ud over den der OutPut-variabel
jo........ jeg pakker de parametre ind i et samlede objekt/klasse, som jeg så kan lave en ny instans af også. Her:
Dim createNewUser As CreateNewUser = New CreateNewUser() createNewUser = userManagement.AddNewUser(ddlUserRightsValue, txtCompanyValue, txtUserNameValue, txtEmailValue, txtPasswordValue)
Er det ikke lige så fedt at gøre som at lave en masse properties som indeholder parametrene?
Den label der, der ligger i samme metode også. Den ved jeg heller ikke hvordan jeg skal omkode, så jeg kan tilgå den fra min code-behind class?? :-(
hvis jeg bare skal lade AddNewUser returnere et tal, skal min metode så se således ud:
Public Function AddNewUser(ByVal ddlUserRightsValue As Integer, ByVal txtCompanyValue As String, ByVal txtUserNameValue As String, ByVal txtEmailValue As String, ByVal txtPasswordValue As String) As Integer Dim con As New SqlConnection(connectionString)
Dim cmd As New SqlCommand("sp_GetUserLoginSpecs", con) 'cmd.CommandType = CommandType.StoredProcedure
'parameter til et email tjek længere nede 'cmd.Parameters.Add("@Email", SqlDbType.NVarChar, 50).Value = txtEmailValue
Try 'åbner conn til Db If con.State <> ConnectionState.Open Then con.Open() End If
'tjekker om email adressen allerede findes i Db 'Dim reader As SqlDataReader = cmd.ExecuteReader() 'If reader.Read = True Then 'blblMsg.Text = "<ul><li>Der findes allerede en bruger med denne email-adresse!</li></ul>" 'blblMsg.ForeColor = Color.Red 'blblMsg.Font.Bold = False 'con.Dispose() 'con.Close() 'Exit Try 'Else 'reader.Close()
'Tilføj bruger i Db tabel User_Accounts cmd = New SqlCommand("sp_UserAdd", con) cmd.CommandType = CommandType.StoredProcedure
'input parametre til tilføjelse af det nye bruger data cmd.Parameters.Add("@Company", SqlDbType.NVarChar, 50).Value = txtCompanyValue
Dim userManagement As UserManagement = New UserManagement() userManagement.AddNewUser(ddlUserRightsValue, txtCompanyValue, txtUserNameValue, txtEmailValue, txtPasswordValue)
Dim intResult As Integer = userManagement ?????? Dim strResult As String '= "Resultat=" & CStr(intResult) & "<br /><br />" '** udskriver resultatet -1, 0 eller 1 **
'select case ud fra en af disse 'output parametre: -1, 0 eller 1 Select Case intResult Case -1 : strResult += "<font style=""color:red;"">Der skete en fejl, og ingen brugerdata er blevet tilføjet!</font>"
Case 0 : strResult += "<font style=""color:red;"">Der skete en fejl, og ingen brugerdata er blevet tilføjet!</font>"
Case Is > 0 : strResult += "<font style=""color:green;"">Bruger dataene blev tilføjet korrekt!</font>" End Select
fårk du tåger mand... har du seriøst selv lavet din UserManagement-klasse?
Dim userManagement As UserManagement = New UserManagement() Dim intResult As Integer = userManagement.AddNewUser(ddlUserRightsValue, txtCompanyValue, txtUserNameValue, txtEmailValue, txtPasswordValue)
hvad med update og delete? Hvilken fremgangsmåde skal jeg bruge der så?
Den reader og label jeg snakker om er den her:
'tjekker om email adressen allerede findes i Db Dim reader As SqlDataReader = cmd.ExecuteReader() If reader.Read = True Then blblMsg.Text = "<ul><li>Der findes allerede en bruger med denne email-adresse!</li></ul>" blblMsg.ForeColor = Color.Red blblMsg.Font.Bold = False con.Dispose() con.Close() Exit Try Else reader.Close()
disco_keld>> nej nej... selvfølgelig ikke... men du gør jo brug af mange ting i din klasse som ligger på et lidt højere niveau... så jeg ville bare gå ud fra at hvis du har forstået alt det der sker i din klasse, så ville du også vide hvad du skulle returnere :)
ang. delete skal du bruge en ExecuteNonQuery, og ligeså med en update... personligt bruger jeg aldrig en reader, synes det er noget snask... du skal forresten heller ikke blande designet ind i din klasse... kast hellere en exception... altså
'tjekker om email adressen allerede findes i Db Dim reader As SqlDataReader = cmd.ExecuteReader() If reader.Read = True Then throw new Exception() con.Dispose() con.Close() Exit Try Else reader.Close()
og ude på din codebehind skruver du så
try Usermanagement.Update(blabla) catch (Exception) blblMsg.Text = "<ul><li>Der findes allerede en bruger med denne email-adresse!</li></ul>" blblMsg.ForeColor = Color.Red blblMsg.Font.Bold = False End try
>> CF...... jeg læser i døgndrift i mine wrox bøger om Class design ovs.
Så jeg bruger meget tid på det, men det er stadig lige så nyt for mig som da jeg syntes html var svært.
Jeg skal lige lære at gennemskue hvilke ting der kalder hvad og hvilke ting der retunere hvad ovs ovs.
Men fuck hvor er det fedt......... mand.
Men du har ret, jeg kludrer lidt i det eller blander lidt ting sammen.
Jeg ved godt man skal bruge ExecuteNonQuery hvis ikke der skal returneres noget. Men jeg tænkte nu mere på min fremgangsmåde m.h.t. at smide parametre i en klasse for sig, og smide det frem og tilbage?
Try Dim userManagement As UserManagement = New UserManagement() Dim intResult As Integer = userManagement.DeleteUserData(ddlUsersValue) Dim strResult As String '= "Resultat=" & CStr(intResult) & "<br /><br />" '** udskriver resultatet -1, 0 eller 1 **
'hvis SPROC returnere et -1 eller 0 "error". hvis > 0 så gennemfør trans. Select Case intResult Case -1 : strResult += "<font style=""color:red;"">Der skete en fejl, og ingen brugerdata blev slettet!</font>"
Case 0 : strResult += "<font style=""color:red;"">Der skete en fejl, og ingen brugerdata blev slettet!</font>"
Case Is > 0 : strResult += "<font style=""color:green;"">Bruger dataene blev slettet korrekt!</font>" End Select Catch ex As Exception bLblMsg.Text = "<ul><li>Der findes allerede en bruger med denne email-adresse!</li></ul>" bLblMsg.ForeColor = Color.Red bLblMsg.Font.Bold = False End Try
Try 'åbner conn til Db If con.State <> ConnectionState.Open Then con.Open() End If
'tjekker om email adressen allerede findes i Db Dim reader As SqlDataReader = cmd.ExecuteReader() If reader.Read = True Then Throw New Exception() con.Dispose() con.Close() Else reader.Close()
'Tilføj bruger i Db tabel User_Accounts cmd = New SqlCommand("sp_UserAdd", con) cmd.CommandType = CommandType.StoredProcedure
'input parametre til tilføjelse af det nye bruger data cmd.Parameters.Add("@Company", SqlDbType.NVarChar, 50).Value = txtCompanyValue
cmd.ExecuteNonQuery() End If Catch Throw Finally If con.State <> ConnectionState.Closed Then con.Dispose() con.Close() End If End Try
når du laver et Throw i If sætningen der, som i forvejen ligger i en Try block så er det jo den Catch der fanger den, og ikke den der ligger i code-behind filen!
altså, tænker du på den der NewUser-klasse du lavede? i så fald var ideen god nok, hvis du altså rent faktisk skulle bruge de værdier der var i NewUsers variabler... som jeg så det skulle du kun bruge OutPut til noget, og derfor var der ikke rigtig nogen grund til at gemme på så meget information.
Et oplagt et eksempel kunne være en vektor, som f.eks. består af to tal... man kunne derfor med fordel oprette følgende type
struct Vector { public int x; public int y;
public Vector(int x, int y) { this.x = x; this.y = y; } }
grunden til at jeg har oprettet den som struct og ikke class, er at struct er en value-type og derfor opbevares på stack'en som er meget hurtigere end heap'en hvor f.eks. klasser befinder sig.
Et andet eksempel kunne være en person...
struct Person { public string Navn; public int Alder;
public Person(string Navn, int Alder) { this.Navn = Navn; this.Alder = Alder; } }
lad os så sige at vi har en funktion i din UserManagement-klasse der tilføjer en person til databasen... den funktion kunne så se sådan her ud:
public void AddPerson(Person p) { string sql = "INSERT INTO personer (navn, alder) VALUES ('"+ p.Navn +"', "+ p.Alder +""); ExecuteNonQuery(sql); }
håber at det afklarede nogle ting, ellers er du altid velkommen at kontakte mig enten via eksperten.dk, icq eller mail :)
Tak for eksemplet Cyberfessor! Det var kanon, det eneste jeg ikke lige er med på, er den sætning her:
"grunden til at jeg har oprettet den som struct og ikke class, er at struct er en value-type og derfor opbevares på stack'en som er meget hurtigere end heap'en hvor f.eks. klasser befinder sig" ?
du nævner sgu nogen ting som godt lige vil vide hvad betyder! ;-)
kaay... det er nu ellers nogle vigtige begreber at kunne hvis man vil udvikle nogle applikationer der yder bare nogenlunde.
valuetypes er typer som opbevares på stacken, mens referencetypes befinder sig på heapen. Både stack og heap er hukommelsen, mens forskellen på dem er hastigheden, hvor stack er det hurtigste. At oprette en instans af en klasse tager også længere tid og er i det hele taget langt mere kompleks end det er at oprette en valuetype.
En anden ting man skal være opmærksom på er måden hvorpå de virker når man tildeler en variabel til en anden... tag f.eks. følgende
int i = 10; int x = i; x += 50; //i indeholder nu 10, og x indeholder 60
Hvis du istedet opretter en instans af en klasse, så forholder det sig anderledes (vi lader lige som om at min Vector-struct, er en class istedet);
Vector i = new Vector(10, 10); Vector u = i; u.x = 20; u.y = 20; //hovsa... nu indeholder båder i og u værdierne 20,20
Hehe......... okay. Jeg har sikkert læst henover det her, eller var gået i koma. Jeg kan lige så godt lægge bogen fra mig, efter 10 min. når jeg er hoppet i boxen. For jeg kan ikke huske halvdelen af det alligelvel. Hehe...
Cool nok,- ikke grine nu fessor :-)
valuetypes = ByVal
referencetypes = ByRef
hvorfor er Stack hurtigst?
du siger at det forholder sig anderledes hvis man laver en ny instans af en class. Vil du ikke lige definere hvad du mener med det?
stack er hurtigst fordi at den ikke bliver fragmenteret... værdier i stacken bliver nedlagt i samme rækkefølge som de bliver oprettet, så derfor skal .Net runtimen ikke holde styr på andet end en stackpointer, som er et tal som refererer til næste sted i stacken som er fri. Når du f.eks. opretter en int-variable bliver der smidt 32 bytes i stacken, stackpointeren stiger med 32 bytes, og når variablen går ud af scope falder stackpointeren igen med 32 bytes. Heapen er lidt mere indviklet, da en .Net runtimen jo ikke kan vide hvor meget en klasse fylder. Derfor skal den søge hukommelsen igennem efter et frit område som er lige så stort som den pågældende klasse fylder. Det er dog heldigvis ikke så slemt som det var i "gamle dage", da Garbage Collectoren sørger for at defragmentere hukommelsen af og til.
Grunden til at eksemplet som jeg viste forholdt sig som det gjorde er følgende:
når jeg skriver int x = i, så bliver VÆRDIEN af i KOPIERET til x. Dvs at x indeholder tallet 10, og når jeg lægger 50 til indeholder x 10+50 = 60. i indeholder dog stadigvæk 10. I ekspemplet med klassen, bliver bliver REFERENCEN (altså adressen til hvor den befinder sig på heapen) til i KOPIERET til u. Dvs at u og i faktisk refererer til samme sted i hukommelsen. Det gør at når jeg sætter u.x til 20, så bliver i.x også sat til 20.
Synes godt om
Ny brugerNybegynder
Din løsning...
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.