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
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.
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
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.
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