SQLite update query works in console, not in .Net - sql

I am using an SQLite database in my application. For some reason the query:
UPDATE USERS SET PASSWORD = 'test' WHERE USERNAME = 'Admin'
works in console (updates the PASSWORD field), but when I run it via code:
Dim exec As String = "UPDATE USERS SET PASSWORD = '" & password & "' WHERE USERNAME = '" & username & "'"
Dim returnCode As [Boolean] = True
Try
ExecuteNonQuery(exec)
Catch
returnCode = False
End Try
Return returnCode
The function always returns false, and the database is not updated. Here is the ExecuteNonQuery method:
Public Shared Function ExecuteNonQuery(sql As String) As Integer
Dim cnn As New SQLiteConnection(dbConnection)
cnn.Open()
Dim mycommand As New SQLiteCommand(cnn)
mycommand.CommandText = sql
Dim rowsUpdated As Integer = mycommand.ExecuteNonQuery()
cnn.Close()
Return rowsUpdated
End Function
What am I doing wrong here? My code for creating a new row works fine, but updating doesn't.
Yes, I am aware this is unsafe, I originally had a bunch more safety checks, but I need to at least get it to work before doing so.

For some reason, sqlite3.dll did not get moved to the output folder along with the application, causing weird behavior and ultimately for the query to fail.
When I placed a copy of the dll into the output folder, everything worked fine.

Related

Check for Object reference not set to an instance of an object

I have a website I am building with asp.net. I am trying to incorporate a username check based off their username of their pc. I get this
Object reference not set to an instance of an object.
When a new user that is not in my SQL Server database tries to access the site. I would like to add an "if" statement that would redirect them to my error page.
What do I put in my if statement to catch that error instead of getting the error page.
Here is part of my code so you can know what names I am using
Dim sqlConnection1 As New SqlConnection("randomserverstuff")
Dim cmd As New SqlCommand
Dim returnValue As Object
cmd.CommandText = "SELECT RESTRICTED FROM USERS WHERE Username='" & Replace(Page.User.Identity.Name, "domain\", "") & "'"
cmd.CommandType = CommandType.Text
cmd.Connection = sqlConnection1
sqlConnection1.Open()
returnValue = cmd.ExecuteScalar()
sqlConnection1.Close()
If Session(returnValue)!= Null) Or returnValue.ToString = "Y" Then
that last line, the first part of the is statement is what I'm trying to build and cant seem to catch that error in it. Any ideas?
This is wrong:
If Session(returnValue)!= Null)
Really, is this vb or c# - neither one!!
Considering that returnValue can be Nothing the right way would be:
If returnValue IsNot Nothing AndAlso Session(returnValue) IsNot Nothing Then
Declare returnValue as String, VB will convert it for you implicitly.
So after no luck I decided to check for row count before running my statement and if rows = 0 to return y and if rows is greater to run a seperate sql statement to determine the result of the restricted column.

Adodb Recordset function .MoveNext Causes Exception "UPDATE permission was denied"

I've run into a problem today that has stumped me.
Here is some sample code:
Dim objRec As ADODB.Recordset
Dim oRec As ADODB.Recordset
Dim oRecBuild As New ADODB.Recordset
cmd = New ADODB.Command()
cmd.ActiveConnection = objConn
cmd.CommandText = "SelectAll_PhoneNumbers_ById"
cmd.CommandType = ADODB.CommandTypeEnum.adCmdStoredProc
cmd.NamedParameters = True
cmd.Parameters.Append(cmd.CreateParameter("#ObjId", ADODB.DataTypeEnum.adVarChar, ADODB.ParameterDirectionEnum.adParamInput, 20, objRec.Fields("PK_ProgramID").Value))
oRec = New ADODB.Recordset()
oRec.Open(cmd, , ADODB.CursorTypeEnum.adOpenStatic, ADODB.LockTypeEnum.adLockOptimistic)
If oRec.EOF = False Then
Do Until oRec.EOF
If IsDBNull(oRec.Fields("PhoneType").Value) = False Then
sName = PhoneNumberEdit(oRec.Fields("Phone").Value)
If IsDBNull(oRec.Fields("Extension").Value) = False And Len(oRec.Fields("Extension").Value) > 0 Then
sName = PhoneNumberEdit(oRec.Fields("Phone").Value) & " " & oRec.Fields("Extension").Value
End If
oRecBuild.AddNew(New Object() {"TextPrint", "TextType"}, New Object() {sName, oRec.Fields("PhoneType")})
End If
oRec.MoveNext()
Loop
End If
When I reach the .MoveNext() function the app throws an error that reads like this: The UPDATE permission was denied on the object 'PhoneNumbers', database 'MyDb', schema 'dbo'.
Nothing in this code block is calling an update (the function calls in the loop are just formatting data), does anyone have any idea of what could be causing this?
I should also add that I can run this using SSPI locally, however the code needs to be able to run on a server using a SQL username and PW; I have tested updates with the app on other pages, and it works fine.
This is just a hunch, but I do see one place in that code that might result in an UPDATE commend: oRecBuild.AddNew(). I don't see how it could, but I wonder if calling oRec.MoveNext() is somehow forcing a commit from oRecBuild. Otherwise, I'd take a longer look at the SelectAll_PhoneNumbers_ById procedure, and any possible triggers that might be attached to tables or views it uses.
And if that fails, I'd do this:
Public Class PhoneNumber
Public Number As String
Public PhoneType As String
End Public
'...
Dim result As New List(Of PhoneNumber)
Using cn As New SqlConnection("connection string"), _
cmd As New SqlCommand("SelectAll_PhoneNumbers_ById", cn)
cmd.CommandType = CommandType.StoredProcedure
'Is this really an integer?
cmd.Parameters.Add("#ObjId", SqlDbType.NVarChar, 20).Value = objRec.Fields("PK_ProgramID").Value
cn.Open()
Using rdr As SqlDataReader = cmd.ExecuteReader()
While rdr.Read()
Dim phone As String = ""
If Not IsDbNull(rdr("PhoneType"))
phone = PhoneNumberEdit(rdr("Phone"))
End If
If Not IsDbNull(rdr("Extension"))
phone = phone & " " & PhoneNumberEdit(rdr("Extension"))
End If
result.Add(New PhoneNumber With {.Number = phone, .PhoneType = rdr("PhoneType")})
End While
End Using
End Using
While I'm at it... anytime you're reading data from one recordset into another there's a very strong chance that the whole thing could be done entirely in the database, with no client code at all.
To close this question, I wanted to go ahead and say that I finally was able to get this resolved. The issue was that dynamic sql being executed with sp_executesql explicitly checks the select, insert, or update privileges of the SQL user; execute privs are NOT enough.
So, either the dynamic SQL has to be done away with or the select/update/insert/delete privs must be granted.
Thank you all for the help and time.

SQLite SELECT from VB.Net application (Win32)

I am trying to get a result from SQL database and keep it as a variable. But with my code (see below) it returns 0 (zero). Any ideas of what am i doing wrong?
Thanks
Function getName(name As String)
Dim SQLconnect As New SQLite.SQLiteConnection()
Dim SQLcommand As SQLite.SQLiteCommand
SQLconnect.ConnectionString = "Data Source=C:\tools\names.sqlite;"
SQLconnect.Open()
SQLcommand = SQLconnect.CreateCommand
SQLcommand.CommandText = "SELECT * FROM names WHERE name = " & name & " LIMIT 1;"
Dim sqlResponse As String = SQLcommand.ExecuteNonQuery()
End Function
EDIT: I am using "return sqlResponse" for return
First thing, the sql should be(I think):
SQLcommand.CommandText = "SELECT * FROM names WHERE name = '" & name & "' LIMIT 1;"
I am not sure how text is represented in SQLite but you need some kind of delimiter like a single quote in SQL Server.
Second thing, use paramterized query to stop yourself from being hijacked by SQL Injections
Third, a SELECT uses a ExecuteReader, and in case where you want only one item, try ExecuteScalar. ExecuteNonQuery is for insert, update delete.
ExecuteNonQuery does not return a value so therefore it will always be 0. You need to use
Dim sqlResponse As String = SQLcommand.ExecuteScalar()

boolean web service method always returns true even when it should not

I have created a vb windows forms webservice in visual studio. I am having an issue where a boolean variable always returns true even when it should not. I am new to VB so it may just be a simple coding error but I just cannot figure it out.
Basically I have a sign in form, the user enters a username, from the form I pass the username to a function in the service called checkuser to see if the user exists in the DB. If the user does it exist it should go to another function to load existing data, if not it should call createuser function.
The variable should return true if user does exist and false if not. However when testing the program the variable always seems to return true even when I input a new username which does not exist.
Here is the form code(login form) which grabs the username and passes it to the checkUser function
Private Sub signInBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles signInBtn.Click
If signInNick.Text = "" Then
MessageBox.Show("Please enter a user name")
signInNick.Focus()
Else
signinName = signInNick.Text
Dim check As Boolean
check = service.checkUser(signinName)
MessageBox.Show(check)
If check = False Then
main.Visible = True
Me.Hide()
main.tbxUserName.Text = signinName
MessageBox.Show("User has been created")
Else
main.Visible = True
Me.Hide()
main.tbxUserName.Text = signinName
MessageBox.Show("Thankyou for Signing In " + signinName)
End If
End If
End Sub
Here is the code for checkUser in the service
'Function to check if a user already exists in the database
<WebMethod()> _
Public Function checkUser(ByVal signinName As String) As Boolean
Dim userToCheck As String
Dim conn As New SqlConnection("Data Source=MARTIN-LAPTOP\SQLEXPRESS;Initial Catalog=musicPlaylist;Integrated Security=True")
Dim sql As String = "SELECT userNick FROM Users WHERE userNick = ('" & signinName & "')"
conn.Open()
Dim objcmd As New SqlCommand(sql, conn)
userToCheck = objcmd.ExecuteScalar()
If userToCheck = signinName Then
getExistingUserPLData(signinName)
Return True
Else
createUser(signinName)
Return False
End If
End Function
The check variable in the form code always seems to return true and this causes the service function to jump to getExistingUserPLData which does not create a user if the user is new.
The strange thing is if I do this through the webservice web page at http://localhost:50445/Service1.asmx, type in a brand new user name and invoke checkUser it will return false if the user does not exist and true if user does exist but it will not work and only return true if done through the form client.
Update: the code provided in one of the answers
If String.Equals(userToCheck, signinName, StringComparison.OrdinalIgnoreCase) Then
appears to work somewhat, as it appears the program is jumpiong to the createUser function if a new username is typed into the login box, but it is giving me an error at the createUser function
Voilation of primary key constraint, cannot insert duplicate key
here is the code for createUser
<WebMethod()> _
Public Function createUser(ByVal signinName As String) As String
Dim conn As New SqlConnection("Data Source=MARTIN-LAPTOP\SQLEXPRESS;Initial Catalog=musicPlaylist;Integrated Security=True")
Dim sql As String = "INSERT INTO Users (userNick) VALUES ('" & signinName & "')"
conn.Open()
Dim cmd As New SqlCommand(sql, conn)
Dim newUserName As String = cmd.ExecuteScalar()
conn.Close()
Return newUserName
End Function
It throws the error at Dim newUserName As String = cmd.ExecuteScalar()
The column userNick is a primary key but I dont understand why it says cannot isert duplicate key when the user does not exist in the database at all, I have checked the DB and username does not already exist, is my code completely wrong?
thanks for your help
Not sure if it is the cause, but your comparison of the username returned from the DB and the input value is case sensitive. When comparing strings, 99% of the time I prefer to use.
If String.Equals(userToCheck, signinName, StringComparison.OrdinalIgnoreCase) Then
'True
Else
'False
End If
Also, the line "signinName = signInNick.Text" is suspect as your code does not indicate what is happening here. Presumably it is a class scoped variable, however it could be a property that is not correctly implemented.
As a side, the line "If signInNick.Text = "" Then" would be better coded as:
If String.IsNullOrWhitespace(signInNick.Text) Then

Inserting variables into a query string - it won't work!

Basically i have a query string that when i hardcode in the catalogue value its fine. when I try adding it via a variable it just doesn't pick it up.
This works:
Dim WaspConnection As New SqlConnection("Data Source=JURA;Initial Catalog=WaspTrackAsset_NROI;User id=" & ConfigurationManager.AppSettings("WASPDBUserName") & ";Password='" & ConfigurationManager.AppSettings("WASPDBPassword").ToString & "';")
This doesn't:
Public Sub GetWASPAcr()
connection.Open()
Dim dt As New DataTable()
Dim username As String = HttpContext.Current.User.Identity.Name
Dim sqlCmd As New SqlCommand("SELECT WASPDatabase FROM dbo.aspnet_Users WHERE UserName = '" & username & "'", connection)
Dim sqlDa As New SqlDataAdapter(sqlCmd)
sqlDa.Fill(dt)
If dt.Rows.Count > 0 Then
For i As Integer = 0 To dt.Rows.Count - 1
If dt.Rows(i)("WASPDatabase") Is DBNull.Value Then
WASP = ""
Else
WASP = "WaspTrackAsset_" + dt.Rows(i)("WASPDatabase")
End If
Next
End If
connection.Close()
End Sub
Dim WaspConnection As New SqlConnection("Data Source=JURA;Initial Catalog=" & WASP & ";User id=" & ConfigurationManager.AppSettings("WASPDBUserName") & ";Password='" & ConfigurationManager.AppSettings("WASPDBPassword").ToString & "';")
When I debug the catalog is empty in the query string but the WASP variable holds the value "WaspTrackAsset_NROI"
Any idea's why?
Cheers,
jonesy
alt text http://www.freeimagehosting.net/uploads/ba8edc26a1.png
I can see a few problems.
You are using concatenation in a SQL statement. This is a bad practice. Use a parameterized query instead.
You are surrounding the password with single quotes. They are not needed and in fact, I'm surprised it even works assuming the password itself does not have single quotes.
You should surround classes that implement IDisposable with a Using block
You should recreate the WASP connection object in GetWASPcr like so:
Public Sub GetWASPAcr()
Dim username As String = HttpContext.Current.User.Identity.Name
Dim listOfDatabaseConnectionString As String = "..."
Using listOfDatabaseConnection As SqlConnection( listOfDatabaseConnectionString )
Using cmd As New SqlCommand("SELECT WASPDatabase FROM dbo.aspnet_Users WHERE UserName = #Username")
cmd.Parameters.AddWithValue( "#Username", username )
Dim dt As New DataTable()
Using da As New SqlDataAdapter( cmd )
da.Fill( dt )
If dt.Rows.Count = 0 Then
WaspConnection = Null
Else
Dim connString As String = String.Format("Data Source=JURA;Initial Catalog={0};User Id={1};Password={2};" _
, dt.Rows(0)("WASPDatabase") _
, ConfigurationManager.AppSettings("WASPDBUserName") _
, ConfigurationManager.AppSettings("WASPDBPassword"))
WaspConnection = New SqlConnection(connString);
End If
End Using
End Using
End Using
End Sub
In this example, listOfDatabaseConnectionString is the initial connection string to the central database where it can find the catalog name that should be used for subsequent connections.
All that said, why would you need a class level variable to hold a connection? You should make all your database calls open a connection, do a sql statement, close the connection. So, five database calls would open and close a connection five times. This sounds expensive except that .NET gives you connection pooling so when you finish with a connection and another is requested to be opened, it will pull it from the pool.
Your string passed into the constructor for this SqlConnection object will be evaluated when the class is instantiated. Your WASP variable (I'm assuming) won't be set until the method you have shown is called.
Might want to quit looking one you have found your database:
For i As Integer = 0 To dt.Rows.Count - 1
If dt.Rows(i)("WASPDatabase") Is DBNull.Value Then
WASP = ""
Else
WASP = "WaspTrackAsset_" + dt.Rows(i)("WASPDatabase")
break
End If
Next
[link text][1]You are building your string on the fly by adding the value of a column to a string. So, for the row in question for the column "WASPDatabase" was tacked on to your string. So you got what it had. On another note, your earlier query of "select ... from ... where ..." where you are manually concatinating the string of a variable makes you WIDE OPEN to SQL-Injection attacks.
Although this link [1]: how to update a table using oledb parameters? "Sample query using parameterization" is to a C# sample of querying with parameterized values, the similar principles apply to most all SQL databases.
At the time you're creating the new connection, WASP is holding the value you want it to be holding? It is a string data type? Try adding .ToString after WASP and see if that helps anything.
Interesting problem. =-)
The problem is, as Paddy already points out, that the WaspConnection object gets initialized before you even have the chance to call GetWASPAcr. Try this:
Public Sub GetWASPAcr()
'[...]
End Sub
Dim _waspConnection As SqlConnection
Public Readonly Property WaspConnection As SqlConnection
Get
If _waspConnection Is Nothing Then
GetWASPAcr()
_waspConnection = New SqlConnection("Data Source=JURA;Initial Catalog=" & WASP & ";User id=" & ConfigurationManager.AppSettings("WASPDBUserName") & ";Password='" & ConfigurationManager.AppSettings("WASPDBPassword").ToString & "';")
End If
Return _waspConnection
End Get
End Property