I have a problem where I am unable to make a booking to a Sql server .mdf database, but I am able to read to it.
No error messages occur and I have tried everything I can think of. Any help will be highly appreciated and thanks in advance!
Here is the code used for the insert into command:
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim SQLCode As New SQLCode
Dim con As New SqlConnection
Dim cmd As New SqlCommand
Dim lrd As SqlDataReader
Dim inscmd As New SqlCommand
cmd.Parameters.AddWithValue("#StaffInitials", lblStaffInitials.Text.Trim())
lblStaffInitials.Text = lblStaffInitials.Text
cmd.Parameters.AddWithValue("#Week", lblWeek.Text.Trim)
lblWeek.Text = lblWeek.Text
cmd.Parameters.AddWithValue("#Period", (lblPeriod.Text.Trim))
lblPeriod.Text = lblPeriod.Text
cmd.Parameters.AddWithValue("#Day", lblDay.Text.Trim)
lblDay.Text = lblDay.Text
cmd.Parameters.AddWithValue("#Subject", lblSubject.Text.Trim)
lblSubject.Text = lblSubject.Text
cmd.Parameters.AddWithValue("#YearGroup", lblYear.Text.Trim)
lblYear.Text = lblYear.Text
cmd.Parameters.AddWithValue("#NumberOfPupils", (lblNoOfPupils.Text.Trim))
lblNoOfPupils.Text = lblNoOfPupils.Text
cmd.Parameters.AddWithValue("#ControlledAssesment", lblControlledAssesment.Text.Trim)
lblControlledAssesment.Text = lblControlledAssesment.Text
cmd.Parameters.AddWithValue("#Room", lblRoom.Text.Trim)
lblRoom.Text = lblRoom.Text
cmd.Parameters.AddWithValue("#Session", txtSession.Text.Trim)
txtSession.Text = txtSession.Text
con.ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings("RoomBookingSystem.My.MySettings.Database1ConnectionString1").ConnectionString
Try
Using cn As New SqlConnection(con.ConnectionString)
con.Open()
inscmd.CommandText = "INSERT INTO Booking (Week, Day, Period, Subject, YearGroup, StaffInitials,NumberOfPupils,Session,Room,ControlledAssesment) VALUES (#Week,#Day,#Period,#Subject,#YearGroup,#StaffInitials, #NumberOfPupils,#Session,#Room,#ControlledAssesment)"
inscmd.Connection = con
inscmd.ExecuteNonQuery()
inscmd.Parameters.Clear()
End Using
Finally
con.Close()
End Try
MsgBox("Your Booking Has Been Made Successfully")
Clicky = False
MainViewForm.btnBackToBooking.Visible = False
FormView.Show()
Me.Hide()
End Sub
As far as I can tell the problem lies within the databases location.
When the program is debugged a copy of your database is placed within the bin/debug folder, if you look in here you will see the copy and your code will right to this database and Not The original Database (if you click show all files then go to the bin/debug file and then open with database explorer you can see the data imputed on the last debug/running)
To fix this you need to do the following:
Your connection string
con.ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings("RoomBookingSystem.My.MySettings.Database1ConnectionString1").ConnectionString
Will connect to the database within the bin folder mentioned previously.
You need to go into your app.config file find the specific location for your database and use this for you connection string, this will allow you to insert/update data from the non copy of the database.
You have two different Sql Commands when only one SqlCommand is needed. Add the parameters to inscmd rather than cmd.
So simply remove this line :
Dim cmd As New SqlCommand
and do this for the rest :
inscmd.Parameters.AddWithValue("#StaffInitials", lblStaffInitials.Text.Trim())
.....
.....
Another thing to note, you don't need this :
Using cn As New SqlConnection(con.ConnectionString)
Change your code like this :
Try
con.Open()
inscmd.CommandText = "INSERT INTO Booking (Week, Day, Period, Subject, YearGroup, StaffInitials,NumberOfPupils,Session,Room,ControlledAssesment) VALUES (#Week,#Day,#Period,#Subject,#YearGroup,#StaffInitials, #NumberOfPupils,#Session,#Room,#ControlledAssesment)"
inscmd.Connection = con
inscmd.ExecuteNonQuery()
inscmd.Parameters.Clear()
Catch ex As Exception
// use message box to read the error (if there is any). or simply read the
// ex.Message in debuggin mode.
Finally
con.Close()
End Try
and by the way I don't see where you are setting this property con.ConnectionString. where is your connection string?
Related
Sorry if its easy or basic i am brand new to sql and tables so im just trying to figure it out
Basically im trying to delete a row that the user selects
By having them click on a row then clicking a delete button but i don't know how that should look ive tried a few different ways but none of them seem to work.
No error comes up but it just dosen't delete the row
Private Sub DeleteSelectedUsers()
Dim connection As SqlConnection = New SqlConnection()
connection.ConnectionString = "Data Source=GERARD-PC\SQLEXPRESS; Initial Catalog=TestDB;User ID=AccountsUser;Password=password123"
connection.Open()
Dim adp As SqlDataAdapter = New SqlDataAdapter _
("Delete * from dgrdUsers.SelectedRows(0).Cells", connection)
End Sub
Private Sub btnDelete_Click(sender As Object, e As EventArgs) Handles btnDelete.Click
Try
Dim username As String = dgrdUsers.SelectedRows(0).Cells.Item("Username").Value.ToString()
If (MessageBox.Show(Me, "Do you want to delete user " & username & "?", "Confirm Delete", MessageBoxButtons.YesNo, MessageBoxIcon.Question) = DialogResult.Yes) Then
DeleteSelectedUsers()
End If
Catch ex As Exception
End Try
End Sub
Any ideas?
The syntax required to delete a row in the database table requires at least three parts.
The DELETE command
The FROM statement to identify the table where the delete action should occur
The WHERE condition to identify the record (or records) to delete
So it is a string like this: DELETE FROM tablename WHERE condition
and applied to your code you get this.
Private Sub DeleteSelectedUsers(userName as String)
Using connection As SqlConnection = New SqlConnection()
connection.ConnectionString = "...."
connection.Open()
Dim cmd As SqlCommand = New SqlCommand _
("DELETE FROM Table WHERE userName = #user", connection)
cmd.Parameters.Add("#user", SqlDbType.NVarChar).Value = userName
cmd.ExecuteNonQuery()
End Using
End Sub
(Table and UserName are fantasy names because we don't know what is the actual schema of your database)
Other things I have changed:
The connection is created inside a using block to be sure a proper
closure and dispose happens even in case of errors
The name of the user to remove should be passed as parameter to the
function
No need to use an adapter when you just need to execute a single
SqlCommand
The query doesn't concatenate strings to build the command but use a
parameter added to the command itself and specifying a type for the
data matching the type on the database table
My connection between my project and my Ms Access 2010 Database seems to be right at the moment of logging in with my project. However, After the first trial(if user and/or password are incorrect), when I try to log in again, the error is given. It says "Connection was not closed. Connection's current State was open". I just have found possible solutions for MySql service, but I'm using Ms Access database. The code where the error seems to be given is the following. Any suggestions?, please:
Public Function Validation()
da.Fill(dt)
connection.Open()
For Each DataRow In dt.Rows
If txtUser.Text = DataRow.Item(0) And txtPassword.Text = DataRow(1) Then
If cmbAccountType.Text = DataRow(2) Then
connection.Close()
Return True
End If
End If
Next
Return False
End Function
Why are you opening the connection in the first place? You're not using it between the Open and Close calls so what's the point? The Fill method will automatically open the connection if it's currently closed and then it will automatically close it again if it opened it, i.e. Fill and Update will open the connection if necessary and then leave it in its original state afterwards. Get rid of both the Open and Close calls.
To begin with, Function's in vb.net require a DataType. I have no idea what da.Fill(dt) is doing in this function. If you didn't have an open connection you wouldn't be able to fill anything but then on the next line you open some unknown connection from somewhere.
OleDb pays no attention to the names of parameters. The position of the parameters in the sql string must match the order that the parameters are added to the parameters collection.
Here is one approach.
Private ConnStr As String = "Your connection string"
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If Validation(txtUser.Text, txtPassword.Text, cmbAccountType.Text) Then
'Do something
End If
End Sub
Public Function Validation(UName As String, PWord As String, Type As String) As Boolean
Dim Count As Integer
Using cn As New OleDbConnection(ConnStr),
cmd As New OleDbCommand("Select Count(*) From SomeTable Where User = #User And Password = #Password And AccountType = #Type;", cn)
cmd.Parameters.Add("#User", OleDbType.VarChar).Value = UName
cmd.Parameters.Add("#Password", OleDbType.VarChar).Value = PWord
cmd.Parameters.Add("#Type", OleDbType.VarChar).Value = Type
cn.Open()
Count = CInt(cmd.ExecuteScalar)
End Using
If Count > 0 Then
Return True
End If
Return False
End Function
Of course you should NEVER store passwords as plain text.
I have written a generic VB.net subroutine that populates a datagrid with the results of a query. The subroutine as one parameter, strQuery, which is a string that can translate to any valid SQL-Server view or stored procedure that returns a recordset. Other than that, there is no constraint on the SQL code, and sending two queries that have entirely different field profiles is a valid proposition.
In order to get this to work, I must completely purge the data grid of whatever dataset had been there previously, thus allowing the control to drop its prior identity and start over, allowing, from scratch, the new dateset to redefine the control's contents.
I have finally solved the problem. Perhaps I should have mentioned that I am using Visual Studio 2010, and that if Hersey were using a later version, then the code that worked for him may not have worked for me. The change to my code is one additional line: setting both the name and datapropertyname to the same name. I noticed that when I went to look at the column view, I noticed that the datapropertyname is how the table links to the source, and the name is an effective alias for the field, how it will be presented. Obviously, for clarity sake, both must be the same! This now works as advertised.
Thanks, ~ Peter Ferber
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim con As New SqlConnection("<Enter Connection string here>")
Dim rcd As ADODB.Recordset = ReturnRecordset("Select * From ExcludeWords")
Call DefineDataGrid("Select * From ExcludeWords")
End Sub
Private Sub btnUpdate_Click(sender As System.Object, e As System.EventArgs) Handles btnUpdate.Click
Call DefineDataGrid("Select * From FindWords")
End Sub
Sub DefineDataGrid(ByVal strQuery As String)
Dim con As New SqlConnection("<Enter Connection String Here>")
Dim dt As New DataTable
FindWordGrid.Columns.Clear()
FindWordGrid.DataSource = Nothing
Dim rcd As ADODB.Recordset = ReturnRecordset(strQuery)
Dim MyField As ADODB.Field
Dim iCount As Integer = -1
FindWordGrid.ColumnCount = rcd.Fields.Count
For Each MyField In rcd.Fields
iCount = iCount + 1
FindWordGrid.Columns(iCount).Name = MyField.Name
FindWordGrid.Columns(iCount).DataPropertyName = MyField.Name
Next
Dim cmd As New SqlCommand(strQuery, con)
Dim da = New SqlDataAdapter(cmd)
da.Fill(dt)
FindWordGrid.DataSource = dt
End Sub
Function ReturnRecordset(strQuery As String) As ADODB.Recordset
Dim con As ADODB.Connection = "<Enter Connection string here>"
ReturnRecordset = New ADODB.Recordset
ReturnRecordset.Open(strQuery, con)
End Function
My setup is easy to reproduce: I am using datasets with only a handful of records in each respective table. The only constraint is that the respective runs must have a different field profile. I have been experimenting with different techniques for much of the day, and I now think it best to get some new grey matter on the subject. Getting this process correctly is the last major hurdle for me, in making a key presentation I wish to make, in lobbying for a job role. Thanks, in advance, for your comments, thoughts, and ideas.
Sincerely, ~ Peter Ferber
So, made a couple modifications to the DefineDataGrid code you've posted. Seems to be working for me. I suspect might be something to do with the life cycle of either your cmd or con objects causing your problem. Parsing a number of different number of queries through to it and it rebuilds the datagridview correctly
Sub DefineDataGrid(ByVal strQuery As String)
Dim dt As New DataTable
FindWordGrid.DataSource = Nothing
Using con As New SqlConnection("Your Connection String Here")
Using cmd As New SqlCommand(strQuery, con)
Dim da = New SqlDataAdapter(cmd)
da.Fill(dt)
FindWordGrid.DataSource = dt
End Using
End Using
End Sub
Changed the obvious module level implementations of con and cmd to local variables, and since both types implement IDisposable, wrapped them in a Using pattern
This is my first post in here, but this forum already helped me a lot.
First, sorry for my English, i'm from Brazil and i'm trying to write without a translator.
I'm developing a software for a supermarket, but i'm having problems with the connection to the database. I'm trying to make all the connections and transactions programmatically (DataSets, BindingSources and so).
I've already managed to connect with SQL Server Express 2008, using a Function ("consulta") inside a Module ("db"):
Dim ad As SqlDataAdapter = New SqlDataAdapter
Function consulta(ByVal tabela As String, Optional opt As Boolean = False, Optional optparam As String = "") As DataSet
Dim ds As New DataSet
Try
Dim connstring As String = "Data Source=NOTEBOOK\SQLEXPRESS;Initial Catalog=SysMarket;Persist Security Info=True;User ID=admin;Password=XXXXXX"
Dim conObj As New SqlConnection(connstring)
Dim sql As String
If opt = True Then
sql = "SELECT * FROM " & tabela & " " & optparam
Else
sql = "SELECT * FROM " & tabela
End If
Dim cmd As SqlCommand = New SqlCommand(sql, conObj)
ad.SelectCommand = cmd
conObj.Open()
ad.Fill(ds, tabela)
ad.Dispose()
cmd.Dispose()
conObj.Close()
Return ds
Catch ex As Exception
MessageBox.Show("Erro na consulta" & vbCrLf & ex.InnerException.ToString, "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error)
ds.Clear()
Return ds
End Try
End Function
And this is a part of the main code where I make a SelectQuery and put into a BindingSource:
Dim ds As DataSet = db.consulta("departamentos")
Private Sub cad_departamento_Load(sender As Object, e As EventArgs) Handles MyBase.Load
BindingSource1.DataSource = ds
BindingSource1.DataMember = "departamentos"
TextBox1.DataBindings.Add("Text", BindingSource1, "id")
TextBox2.DataBindings.Add("Text", BindingSource1, "departamento")
End Sub
But my problem is when I have to Update the database, by adding, editing or deleting some item from BindingSource. Because in the Module I've closed the connection to the SQL Server. So I will need reopen this connection and then, somehow "read" the DataSet with the change and Update the database?
Someone could explain this to me or show me a example?
Thank you.
You will use a data adapter to save the data, just as you used one to retrieve the data. You will have to create an InsertCommand if you want to insert new records, an UpdateCommand if you want to update existing records and a DeleteCommand if you want to delete existing records. You can write those yourself or, if the conditions are right, you can use a command builder to do it for you.
If your query is based on a single table and you want to insert/update all the columns you retrieve back to that same table then a SqlCommandBuilder may be your best bet. You simply pass in the query and the command builder will use it to generate the action commands. That gives you limited flexibility but if you're just doing single-table operations then you don't need that added flexibility.
Such a method might look something like this:
Public Sub SaveChanges(tableName As String, data As DataSet)
Dim query = "SELECT * FROM " & tableName
Using adapter As New SqlDataAdapter(query, "connection string here")
Dim builder As New SqlCommandBuilder(adapter)
adapter.Update(data, tableName)
End Using
End Sub
I did what you said, but when I open the Form again, the new data are not there.
I made some changes in the code, perhaps because it did not work
Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click
BindingSource1.EndEdit()
ds.AcceptChanges()
db.SaveChanges("departamentos", "INSERT INTO departamentos VALUES('', " & TextBox2.Text & ")", ds)
ds = db.consulta("departamentos")
End Sub
And the code in the Module
Function SaveChanges(tableName As String, query As String, data As DataSet)
Using adapter As New SqlDataAdapter(query, "Data Source=NOTEBOOK\SQLEXPRESS;Initial Catalog=SysMarket;Persist Security Info=True;User ID=admin;Password=XXXXX")
Dim builder As New SqlCommandBuilder(adapter)
adapter.Update(data, tableName)
Return True
End Using
End Function
Yeah this is a pretty simple topic, but my form just isn't updating the row in the database:
Here's my code:
Protected Sub btnSubmit_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSubmit.Click
If Request.QueryString("a") = "edit" Then
Dim CategoryText As String = lstCategory.SelectedItem.Text
Dim conn As New SqlConnection("Data Source=.\SQLEXPRESS; Initial Catalog=LogansArchive; Integrated Security=True;")
Dim cmd As New SqlCommand("UpdateArticle", conn)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.AddWithValue("#ArticleID", Request.QueryString("i"))
cmd.Parameters.AddWithValue("#Category", CategoryText)
cmd.Parameters.AddWithValue("#ArticleTitle", txtNewTitle.Text)
cmd.Parameters.AddWithValue("#ArticleContent", txtContent.Text)
conn.Open()
cmd.ExecuteNonQuery()
conn.Close()
Else
Dim CategoryText As String = lstCategory.SelectedItem.Text
Dim conn As New SqlConnection("Data Source=.\SQLEXPRESS; Initial Catalog=LogansArchive; Integrated Security=True;")
Dim cmd As New SqlCommand("AddArticle", conn)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.AddWithValue("#Category", CategoryText)
cmd.Parameters.AddWithValue("#Date", Now)
cmd.Parameters.AddWithValue("#ArticleTitle", txtNewTitle.Text)
cmd.Parameters.AddWithValue("#ArticleContent", txtContent.Text)
conn.Open()
cmd.ExecuteNonQuery()
conn.Close()
End If
End Sub
Here's the SP that the code refers to:
ALTER PROCEDURE [dbo].[UpdateArticle]
-- Add the parameters for the stored procedure here
#ArticleID int,
#Category varchar(20),
#ArticleTitle varchar(100),
#ArticleContent text
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
UPDATE Articles
SET
Articles.Category = (SELECT CategoryID FROM Categories WHERE CategoryName = #Category),
Articles.ArticleTitle = #ArticleTitle,
Articles.ArticleContent = #ArticleContent
WHERE Articles.ArticleID = #ArticleID
END
I've never used nested SELECTs in SQL before so I'm not sure if I did it right.
Aside from that, this is all stuff I've done before so I'm relatively sure that it's all correct.
Finally, there are no errors being reported when I debug, although the updates don't seem to be coming through from the text fields (txtContent.Text isn't changing to reflect the new value).
Thanks in advance for your assistance.
EDIT 1:
Thanks for the updates, I've looked at the CInt(Request.Querystring("i")) issue, and it doesn't solve the problem. I set a breakpoint on the start of the procedure and hovered over txtContent.Text to check the value of it's Text property in the intellisense. Bear in mind that the debugger is still on the first line of the procedure. The txtContent.Text property as shown by the debugger at this point contains none of the changes I made while testing.
Sometimes I find refactoring code to remove duplication can be really helpful in debugging (and long-term maintenance). Here is your code with the duplicated logic centralized a bit. My guess is that your problem is that you are passing a String instead of an Integer to your SP for ArticleID. You'll see that I did a CInt(Request.QueryString("i")) to ensure that you got an integer to work with instead of the string that Request.QueryString("i") returns.
You may also want to look at my TODO comment and put a breakpoint there and use the debugger to make sure that everything you expect made its way into the cmd.Parameters collection.
As far as the stored procedure goes, I don't see anything wrong with it.
Protected Sub btnSubmit_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnSubmit.Click
Dim categoryText As String = lstCategory.SelectedItem.Text
Dim articleTitle = txtNewTitle.Text
Dim articleContent = txtContent.Text
Dim conn As New SqlConnection("Data Source=.\SQLEXPRESS; Initial Catalog=LogansArchive; Integrated Security=True;")
Dim cmd as SqlCommand
If (Request.QueryString("a") = "edit") Then
Dim articleId = CInt(Request.QueryString("i")) ' Convert provided Article ID to Int
cmd = New SqlCommand("UpdateArticle", conn)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.AddWithValue("#ArticleID", articleId)
Else
cmd = New SqlCommand("AddArticle", conn)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.AddWithValue("#Date", Now)
End If
cmd.Parameters.AddWithValue("#Category", categoryText)
cmd.Parameters.AddWithValue("#ArticleTitle", articleTitle)
cmd.Parameters.AddWithValue("#ArticleContent", articleContent)
' TODO: Put a breakpoint here and inspect cmd.Parameters to be sure they all contain what you expect them to contain.
conn.Open()
cmd.ExecuteNonQuery()
conn.Close()
End Sub
Well it's taken 3 months, but I just found the answer.
The reason the debugger doesn't see any changes to my text fields is ... wait for it...
The fields are being populated from the database on page load.
I just had the same problem at work, and one of the other developers hit me with this. To fix the problem, place the code that populates the form into the following IF statement:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
' Populate the form out of the database here
End If
End Sub