webForumDet fria alternativet

mysql skumt fel?

.NET

19 svar · 475 visningar · startad av P

Medlem sedan jan. 20012 204 inlägg
Frågan#1

Dett kanske är en fråga för mysql-forumet men eftersom det är asp.net så postar jag den här... Jo har en enkel tabell: UserId|UserName|Password

Och så kör jag denna sql:

SELECT * FROM tbl_users WHERE Username = '"& strUsername &"' AND Password='" & strPassword & "'

Värderna finns i variablerna men får felmeddeladet:

ERROR [42S22] [TCX][MyODBC]Unknown column 'lala' in 'where clause'

:q

Det fungerar om jag kör en vanlig SELECT * FROM abba men lägger jag till WHERE så klagar den...

Medlem sedan dec. 20003 563 inlägg
#2

SQL-Injections?
Kan det vara att du skickar med ett värde som är t.ex. 'lala
Alltså med en apostrof eller likn?

Medlem sedan jan. 20012 204 inlägg
#3

Mm det är det som är fel... hittar dock inget användbart i manualen om "Replace"

Medlem sedan dec. 19996 522 inlägg
#4

Har du provat å byta ut alla ' tecken med dubble ' tecken

Medlem sedan dec. 19996 522 inlägg
#5

Prova med RegEx.Replace,

Regex.Replace(Värdesomskaersättas," '' ", " ' ")

skriv in det i en funktion eller använd dig av sql parameters som fixar det automatiskt

Medlem sedan jan. 20012 204 inlägg
#6

bort!

Medlem sedan dec. 2000399 inlägg
#7

Jo, det borde fungera att göra det så. Det snyggaste sättet att lösa det på är genom att använda OleDbParameter. Kolla dessa två artiklar: http://www.mysql.com/articles/dotnet/#ADO.NET och http://www.dotnet247.com/247reference/a.aspx?u=http://www.4guysfromrolla.com/webtech/092601-1.shtml

Medlem sedan mars 20002 836 inlägg
#8

Varför använda OleDbParameter mot en MySQL Databas????

Själv jobbar jag uteslutande mot Microsoft.Data.Odbc och använder mig således utav OdbcParameters

En annan sak är att man får bättre prestanda med en System-DSN och Microsoft.Data.Odbc än att ange allt i conn-stringen, dsn-less

För att använda OdbcParameters:

'## -- fråga för att hämta specifik post/poster från databasen. --
'## -- frågetecknet är till för att parameter ska kunna läggas till --
Dim querySomething As String = "SELECT * FROM tbl_users WHERE Username = ? AND Password = ?"

'## -- skapa connobject --
Dim cnn As New OdbcConnection("DSN=MySystemDSN")

'## -- skapa command object. vi sätter inte sql-frågan direkt
'##    för att den läggs till i egenskapen CommandText, funkar inte med parameters annars. --
Dim cmd As New OdbcCommand("",cnn)

'## -- vilken sql-fråga som ska köras --
cmd.CommandText = querySomething

'## -- skapa parameter av rätt typ --
Dim paramUsername = New OdbcParameter("@Username",DbType.String)
paramUsername.Value = "Username"

'## -- lägg till parametern till command-objectet --
cmd.Parameters.Add(paramUsername)

'## -- skapa parameter av rätt typ --
Dim paramPwd = New OdbcParameter("@Password",DbType.String)
paramPwd.Value = "Password"

'## -- lägg till parametern till command-objectet --
cmd.Parameters.Add(paramPwd)
Try
	cnn.Open
	Dim dr As OdbcDataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection)
	While dr.Read()
		'## -- gör vad som ska göras --
	End While
Catch Ex As OdbcException
	Throw(Ex)
End Try

ngt sådant .... hoppas att du förstår principen

cya,
PatrikB

Medlem sedan jan. 20012 204 inlägg
#9

Jo jag använer också Odbc. Sen har jag gjort en "dbwrapper" så att jag enkelt kan ändra databas. Fungerar fin-fint med vanliga sql kommandon.

Exakt vad tjänar man på att använda Parametrar? Skyddar mot sql-injections eller?

Kan man använda det i access också?

Medlem sedan mars 20002 836 inlägg
#10

jepp, skyddar mot att fel typer av data kommer in, behöver inte oroa sig för sql-injections m.m

Jepp, det finns stöd för parameters i Oledb och SqlClient oxå:

- OledbParameters
- SqlParameters

Kika i SDKn för NET och läs mer om dem.

Även om du har en Wrapper så kan du bygga in parameter funktionalitet i den oxå .... för de olika managed providerna som wrappern stöder.

Kika på IDataParameter interfacet i SDKn

cya,
PatrikB

Medlem sedan jan. 20012 204 inlägg
#11

japp ska göra det...

Medlem sedan jan. 20012 204 inlägg
#12

Har hållt på ett tag nu på morgonen men har inte fått det att fungera... Vet inte ens om jag tänker rätt!
Det jag försöker göra: Returnera ett dataset med parametrar
kod utdrag: det mest relevanta

        Public Function GetUser(strUserName As String, strPassword as String, intSysId as Integer)
            Dim strSql as String = "(SELECT * FROM tbl_users Where username=@username and password=@password)"
            Dim Params As New Collection()
            Dim Param As IDataParameter
            
            Param = New IDataParameter("@Username",strUserName) ' felraden
            Params.Add(Param)
            Param = New IDataParameter("@Password",strPassword) 'felraden
            Params.Add(Param)
            
            
            Return GetDataSet(strSql, Params)
        End Function
        Function GetDataSet(SqlStatement As String, ByVal Parameters As Collection) As DataSet
            SetDbType()
            Try
                Dim objDataSet as New DataSet()
                objCnn.Open()
                objDataAdapter.SelectCommand = CreateCommand(SqlStatement)
                
                Dim Param As IdbDataParameter
                For Each Param in Parameters
                    objDataAdapter.SelectCommand.Parameters.Add(param)
                Next
                
                objDataAdapter.Fill(objDataSet)
                Return objDataSet
            Catch Exp as SqlException
                Throw exp
            Finally 
                objCnn.Close()
            End Try
        End Function

Felmeddelande vid kompilering:
error BC30375: 'New' cannot be used on an interface.

Jobbigt att det är så lika namn på IdbDataParameter och IDataParameter, vilket borde man använda?

Sen kanske man borde byta ut "Collection" mot "ParameterCollection",såg i en annan tråd att det hade använts, men det får nog bli i ett senare skede om allt fungerar någon gång.

Medlem sedan dec. 2000399 inlägg
#13

Du kan inte skapa objekt av interface. Men SqlParameter implementerar det interfacet så detta borde fungera bättre:

[kod]
Dim Param As SqlParameter

        Param = New SqlParameter("@Username",strUserName)
        Params.Add(Param)
        Param = New SqlParameter("@Password",strPassword)
        Params.Add(Param)

[/kod

Medlem sedan jan. 20012 204 inlägg
#14

hmm sqlparameter är den bara till för mssql?

Medlem sedan mars 20002 836 inlägg
#15

Du kan göra så här:

Dim paramUser As IDataParameter

Select Case DatabaseType
	Case "Oledb"
		paramUser = New OledbParameter("ParameterName", DbType.String)
		paramUser.Value = "Mitt värde"

	Case "Odbc"
		paramUser = New OdbcParameter("ParameterName", DbType.String)
		paramUser.Value = "Mitt värde"

	Case "SqlClient"
		paramUser = New SqlParameter("ParameterName", DbType.String)
		paramUser.Value = "Mitt värde"

End Select

cya,
PatrikB

Medlem sedan jan. 20012 204 inlägg
#16

mjo PatrikB men det blir ju omständigt att ha så där i varje Funktion. Får försöka göra en funktion som jag skickar in dem till...

Medlem sedan mars 20002 836 inlägg
#17

Det är därför som man använder sig av en Wrapper för att sköta alla "standard" grejjer som att skapa connection, command, parameters etc. ..... dvs, om du lägger till hanteringen av Parameters i din Wrapper så behöver du endast skapa detta en gång eftersom wrappern återvinns i alla BDA-object.......

Själv har jag en sådan wrapper som skapar rätt connection, command, parameter object "on-the-fly" beroende på vilken DBMS (Oledb, SqlClient, Odbc, dbProvider) jag vill använda.

Min wrapper har typ dessa publika egenskaper/metoder:

- DatabaseType As String
- ConnectionString As String

- GetDataReader(query) As IDataReader
- CreateParameter(paramName As String, paramType As DbType) As IDataParameter
- SetParameter(param As IDataParameter)

Sedan i mitt BDA-object (som wrappern har ärvts ned i) har jag tex en funktion för att hämta info om en speciell användare, i detta fall:

            Public Function GetUserByID(ByVal userID As Integer) As UserInfo
            
                Dim queryUser As String = "SELECT * FROM Users WHERE User_UserID = ?"
                Dim paramUserID As IDataParameter
                Dim _userInfo As New UserInfo()
                
                '## -- create parameter to handle userid --
                paramUserID = CreateParameter("@UserID", DbType.Int32)
                paramUserID.Value = userID
                
                '## -- add parameter to parameter-collection --
                SetParameter(paramUserID)
                
                Try
                    Dim _dr As IDataReader = GetDataReader(queryUser)
                    
                    If _dr.Read() Then
                        _userInfo.UserID = _dr("User_UserID")
                        _userInfo.Username = _dr("User_Username")
                    End If
                Catch Ex As Exception
                    '## -- error handling --
                End Try
                Return _userinfo
            End Function

I mitt BL har jag då satt vilken db-type jag vill använda och får tillbaka ett object (som för mig och mitt team är generellt) med info om användaren.

Som du ser, så har jag endast kodat wrappern en endaste gång och som sedan återanvänds i alla mina BDA-object

Går säkert att göra allt detta på ett smidigare sätt. Men, detta funkar perfa för mig (och teamet) då vi inte behöver "tänka" på vilken DBMS som ska användas.

cya,
PatrikB

Medlem sedan jan. 20012 204 inlägg
#18

Ahh verkar smart! Har lite kod att skriva om sen!

En fråga bara: "SELECT * FROM Users WHERE User_UserID = ?"

Ska man använda ett ? där?. Vad jag har lärt mig så kör man med @namnet_på_paramtern eller lägger du till den senare?

Medlem sedan mars 20002 836 inlägg
#19

Mot OdbcParameter (går även mot OledbParameter, SqlParamater) så måste man använda ? istället för parametername. Parametername sätts ändå.

Sedan måste man skapa parametrarna i den ordning som ?-tecknet kommer i, där själva parametern ska inkluderas så att säga.

cya,
PatrikB

Medlem sedan jan. 20012 204 inlägg
#20

Tack för koden PatrikB, fungerar utmärkt! (Räddaren i nöden som alltid!)

Har dock en sista fundering. Finns det någon form av "variant" i vb.net? Det jag skulle vilja göra är följande (för att spara kod och tid):
Slå samman din kod till denna:

        Public Function test()
            Dim strSql as String = "SELECT * FROM tbl_users Where Username=?"
            CreateParameter("@Uname",DbType.String,"erik")
            
            Return GetDataSet(strSql)
        End Function

Då skickar jag med namnet, typen och värdet. Hämtar det med denna funktion, som finns i dataklassen.

        Function CreateParameter(ParamName As String, ParamType As DbType, ParamValue As String) As IDataParameter
            Select Case strCnnDBType
                Case "Mysql"
                Parameter = New OdbcParameter(ParamName,ParamType)
                Parameter.Value = ParamValue 
                   
            End Select
                ParamCollection.Add(Parameter)
        End Function

Denna kod ligger då i databas klassen.

Det fungerar utmärkt ovan i detta fall men! Jag har ju Dimentionerat "ParamValue as String" - Skulle man kunna byta ut detta mot någon form av variant? Och sedan kontrollera mot DbType om den är av rätt typ?

Blev ganska rörigt men men...

772 ms totalt · 4 externa anrop · v20260731065814-full.a51de22e
630 ms — deklarationer (db)
0 ms — hämta statistik (cache)
139 ms — hämta tråd, inlägg och bilagor (db)
628 ms — ändringar (db)