I am new here and only signed up because I desperately need the solution to my problem. I have a VB.NET project that is using a local .MDF file that I have imported into my project. The primary keys are intact so I know that isn't my issue.
I am using Linq-to-SQL to query the database and make changes. On my main form I use a Data Grid View that is populated by a query. I am having an issue with my insert where the query works fine and the DGV gets updated with newly created data, but when I call SubmitChanges() the changes do not get saved to the actual physical database. I am not sure what I am missing or doing wrong.
Here is my code to better assist your educated answer.
Public Class frmCell_Leader
'Reference DataContext
Private db As New MarquardtClassesDataContext()
Private Sub frmCell_Leader_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
FillProductionGrid()
PrepareInsertFields()
End Sub
Private Sub FillProductionGrid()
''''''''''''''''''''''''''''''''''
'E.Salce Last Modified 11.29.2012
'Comments: Working
''''''''''''''''''''''''''''''''''
'Populate DGV
Dim query = From marq In db.tblProductivities
Select
marq.PartNum, marq.Produced, marq.Packed, marq.Issue, marq.StationNum, _
marq.PlanDownTime, marq.UnplannedDownTime, marq.CurDate
dgvProduction.DataSource = query
End Sub
Private Sub PrepareInsertFields()
''''''''''''''''''''''''''''''''''
'E.Salce Last Modified 11.29.2012
'Comments: Working
''''''''''''''''''''''''''''''''''
'Fill Planned Downtime Combo Box
Dim PlannedQuery = From planned In db.tblPlannedDownTimes
Select planned.Plan_ID, planned.Description, planned.Active
Where Active = True
cboPlanned.DataSource = PlannedQuery
cboPlanned.DisplayMember = "Description"
cboPlanned.ValueMember = "Plan_ID"
'Fill UnPlanned Downtime Combo Box
Dim UnPlannedQuery = From unplanned In db.tblUnplannedDownTimes
Select unplanned.Unplan_ID, unplanned.Description, unplanned.Active
Where Active = True
cboUnplanned.DataSource = UnPlannedQuery
cboUnplanned.DisplayMember = "Description"
cboUnplanned.ValueMember = "UnPlan_ID"
End Sub
Private Sub btnAdd_Click(sender As System.Object, e As System.EventArgs) Handles btnAdd.Click
'Add the new Production to database
'Create an productivity object
Dim marqpro As New tblProductivity With {
.PartNum = CShort(txtPartNumber.Text),
.Produced = CShort(txtProduced.Text),
.Packed = CShort(txtPacked.Text),
.Issue = txtIssue.Text,
.PlanDownTime = CShort(cboPlanned.SelectedValue),
.UnplannedDownTime = CShort(cboUnplanned.SelectedValue),
.CurDate = Date.Today}
'insert newly created data
Try
'Submit changes too database
db.tblProductivities.InsertOnSubmit(marqpro)
db.SubmitChanges()
db.Refresh(Data.Linq.RefreshMode.KeepCurrentValues, marqpro)
'Refresh DGV
FillProductionGrid()
MessageBox.Show("Data added successfully")
Catch ex As Exception
MessageBox.Show("Error: " & ex.Message)
End Try
End Sub
End Class
Perhaps you have an .mdf file in your project that is getting copied to the bin/debug folder everytime you build.
Why isn't my SubmitChanges() working in LINQ-to-SQL?
Related
When I enter the fields it works and sends the records to the database and if I clear the form and enter another it also sends that one to the database but when I stop debugging, the database is empty.
Is there something wrong with my code?
What should I do to resolve this issue?
• I am using VB.NET with a Microsoft Access database
• There are two pages of code: Control and Create Account Form
Control
Imports System.Data.OleDb
Public Class DBControl
'CREATE YOUR DB CONNECTION
Private DBCon As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;" &
"Data Source=Hotel.mdb;")
'PREPARE DB COMMAND
Private DBCmd As OleDbCommand
'DB DATA
Public DBDA As OleDbDataAdapter
Public DBDT As DataTable
'QUERY PARAMETERS
Public Params As New List(Of OleDbParameter)
'QUERY STATISTICS
Public RecordCount As Integer
Public Exception As String
Public Sub ExecQuery(Query As String)
'RESET QUERY STATS
RecordCount = 0
Exception = ""
Try
'OPEN A CONNECTION
DBCon.Open()
'CREATE DB COMMAND
DBCmd = New OleDbCommand(Query, DBCon)
'LOAD PARAMS INTO DB COMMAND
Params.ForEach(Sub(p) DBCmd.Parameters.Add(p))
'CLEAR PARAMS LIST
Params.Clear()
'EXECUTE COMMAND & FILL DATABASE
DBDT = New DataTable
DBDA = New OleDbDataAdapter(DBCmd)
RecordCount = DBDA.Fill(DBDT)
Catch ex As Exception
Exception = ex.Message
End Try
'CLOSE YOUR CONNECTION
If DBCon.State = ConnectionState.Open Then DBCon.Close()
End Sub
'INCLUDE QUERY & COMMAND PARAMETERS
Public Sub AddParam(Name As String, Value As Object)
Dim NewParam As New OleDbParameter(Name, Value)
Params.Add(NewParam)
End Sub
End Class
Create Account Form
Imports System.Data.OleDb
Public Class Create
Private Access As New DBControl
Private DBCon As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;" &
"Data Source=Hotel.mdb")
Private Sub Create_Load(sender As Object, e As EventArgs) Handles MyBase.Load
If DBCon.State = ConnectionState.Closed Then DBCon.Open() : Exit Sub
End Sub
Private Sub btnCreate_Click(sender As Object, e As EventArgs) Handles btnCreate.Click
AddUser()
End Sub
Private Sub btnCancel_Click(sender As Object, e As EventArgs) Handles btnCancel.Click
txtForename.Clear()
txtSurname.Clear()
txtNumber.Clear()
txtEmail.Clear()
txtPass.Clear()
txtCity.Clear()
End Sub
Private Sub cbxTitle_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cbxTitle.SelectedIndexChanged, txtFirst.TextChanged, txtSurname.TextChanged, txtEmail.TextChanged, txtPass.TextChanged
If Not String.IsNullOrWhiteSpace(cbxTitle.Text) AndAlso Not String.IsNullOrWhiteSpace(txtFirst.Text) AndAlso Not String.IsNullOrWhiteSpace(txtSurname.Text) AndAlso Not String.IsNullOrWhiteSpace(txtEmail.Text) AndAlso txtPass.Text.Length = 8 Then
btnCreate.Enabled = True
End If
End Sub
Private Sub AddUser()
'ADD PARAMETERS
Access.AddParam("#Title", cbxTitle.Text)
Access.AddParam("#Forename", txtForename.Text)
Access.AddParam("#Surname", txtSurname.Text)
Access.AddParam("#Number", txtNumber.Text)
Access.AddParam("#Email", txtEmail.Text)
Access.AddParam("#Pass", txtPass.Text)
Access.AddParam("#City", txtCity.Text)
'EXECUTE INSERT COMMAND
Access.ExecQuery("INSERT INTO Customers([Title], [Forename], [Surname], [Number], [Email], [Pass], [City])" &
"VALUES(#Title, #Forename, #Surname, #Number, #Email, #Pass, #City)")
'REPORT & ABORT ON ERRORS
If Not String.IsNullOrEmpty(Access.Exception) Then MsgBox(Access.Exception) : Exit Sub
DBCon.Close()
End Sub
End Class
Any help is appreciated
Thank you in advance :)
There is a proper way to work with file-based databases in VB.NET.
Add the data file to your project in the Solution Explorer. If you're prompted to copy the file into the project, accept.
Set the Copy To Output Directory property of the data file to Copy If Newer.
Use "|DataDirectory|" to represent the folder path of the data file in your connection string, e.g. Dim connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\Hotel.mdb;".
Now you have two copies of your database. You have the one in the project folder, with the other source files, and the one in the output folder, with the EXE. The source file should stay clean, unsullied by test data. The copy in the output folder is the one you connect to when you debug so that's the one you need to look in to find any changes you make while debugging/testing.
Because you set it to only copy when the source file is newer than the output file, any changes you make while testing will not be lost unless you actually make a change to the source file, e.g. add a column or a table. By default, that property is set to Copy Always, which means that your source file is copied over the output file every time the project is built, so any time any source file changes and you run the project again. That's why your data "disappears".
I have a conundrum.
In my VB.net program, in multiple places I communicate with my SQLserver database. I use Insert, Update and Select statements. My program is made up of multiple forms and my database has 4 tables.
All but one of my subs is working, and despite using break-points and walk through's of the code I can not figure out why.
The form and database tables in question are fine with the select and Insert statements are fully functioning, however the code of the update statement is not. When I run a walk through it behaves as if it has sent the data to the database, however the database never receives it. The connection data is identical to the functioning subs, and the code is in the same format as my update code in other forms within my program. So I can't see why its not working.
Here is the code:
Public selectedDeviceNumber As String = ""
Public selectedDeviceRowNumber As Integer = 0
'================================
'= Set up the DATASETS! =
'================================
Dim PCBconnectionstring As String = "Data Source=ServerName;Initial Catalog=Databasename;User Id=UserId;Password=password;Connect Timeout=30;User INstance=False"
Dim PCBsqlconnection As New SqlClient.SqlConnection(PCBconnectionstring)
Dim damyPCB As New SqlDataAdapter
Dim dsmyPCB As New DataSet
Dim ALcon As New SqlConnection
Dim ALcmd As New SqlCommand
Dim PCBcmd As New SqlCommand
Dim PCBcon As New SqlConnection
'================================
'= SAVE the data! =
'================================
Dim test As String = Me.selectedDeviceNumber
Private Sub SaveToDataBaseFunctionPCB()
'update the data entered to the database
Try
PCBsqlconnection.ConnectionString = "Data Source=ITWIN10-PC\SQL2010;Initial Catalog=SLE1000;User Id=UserId;Password=password;Connect Timeout=30;User Instance=False"
PCBsqlconnection.Open()
PCBcmd.Connection = PCBsqlconnection
PCBcmd.CommandText = "UPDATE PCBlist SET pcbSerial=#pcbSerial,pcbPart=#pcbPart,pcbVent=#pcbVent,pcbDesc=#pcbDesc," & _
"pcbTested=#pcbTested,pcbU1=#pcbU1,pcbU5=#pcbU5,pcbU7=#pcbU7,pcbU10=#pcbU10,pcbU11=#pcbU11,pcbVersion=#pcbVersion," & _
"pcbTestIni=#pcbTestIni,pcbApplyIni=#pcbApplyIni,pcbTestDate=#pcbTestDate,pcbApplyDate=#pcbApplyDate WHERE pcbID=#pcbID "
PCBcmd.Parameters.AddWithValue("#pcbSerial", txtSerialPCB1.Text)
PCBcmd.Parameters.AddWithValue("#pcbPart", cboPartPCB1.Text)
PCBcmd.Parameters.AddWithValue("#pcbVent", txtVentPCB1.Text)
PCBcmd.Parameters.AddWithValue("#pcbDesc", txtDescriptPCB1.Text)
PCBcmd.Parameters.AddWithValue("#pcbTested", chkTested1.Checked)
PCBcmd.Parameters.AddWithValue("#pcbU1", txtU11.Text)
PCBcmd.Parameters.AddWithValue("#pcbU5", txtU51.Text)
PCBcmd.Parameters.AddWithValue("#pcbU7", txtU71.Text)
PCBcmd.Parameters.AddWithValue("#pcbU10", txtU101.Text)
PCBcmd.Parameters.AddWithValue("#pcbU11", txtU111.Text)
PCBcmd.Parameters.AddWithValue("#pcbVersion", txtVersionPCB1.Text)
PCBcmd.Parameters.AddWithValue("#pcbTestIni", txtTestPCB1.Text)
PCBcmd.Parameters.AddWithValue("#pcbApplyIni", txtApplyPCB1.Text)
PCBcmd.Parameters.AddWithValue("#pcbTestDate", txtTestDatePCB1.Text)
PCBcmd.Parameters.AddWithValue("#pcbApplyDate", txtApplyDatePCB1.Text)
PCBcmd.Parameters.AddWithValue("#pcbID", Me.selectedDeviceNumber)
PCBcmd.ExecuteNonQuery()
PCBcmd.Parameters.Clear()
PCBsqlconnection.Close()
MsgBox("Data updated")
Catch ex As Exception
MessageBox.Show(ex.Message)
Finally
PCBsqlconnection.Close()
End Try
End Sub
`Private Sub btnAmend_Click(sender As System.Object, e As System.EventArgs) Handles btnAmend.Click
'Save the data to SQL Server
SaveToDataBaseFunctionPCB()
'record activity in Activity Log
FrmSLE1000.txtActivityLogRecorder.Text = ("Data Saved")
'Save the Activity log data to SQL Server
SaveToDataBaseFunction1()
'SLE1000SqlConnection = New SqlConnection(frmConnections.lblDBConnection.Text & frmConnections.lblDBConnection2.Text)
End Sub
If you have any ideas then please let me know. It could be that I've been looking at the code too long and its obvious, however I can't see the problem.
Many thanks
After extensive fiddling with my code I have fixed the problem. As it turns out the problem lay further back in the code. When the Select statement was called it loaded the data into a list view, which you then select a row which you want to edit. The catch ex as exception was being fired at this point, however the data was still being passed to the text boxes so that you could edit the data, so I mentally 'parked' that glitch for later. In solving that glitch the "amend" button and Update function works fine.
If you're interested the original glitch in the code was as follows
Private Sub lvPCB1_DoubleClick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lvPCB1.DoubleClick
Dim newmachine As String = FrmSLE1000.txtNo.Text
Try
If lvPCB1.SelectedItems.Count = 0 Then
MessageBox.Show("Ensure that you have selected a PCB Board. Try again.")
Exit Sub
Else
'Set selected units ID number in varable to allow access to all row data to populate tables
selectedDeviceNumber = lvPCB1.SelectedItems(0).Text
PopulateTablesFunctionPCB()
txtSerialPCB1.Text = lvPCB1.SelectedItems(1).Text
'record activity in Activity Log
End If
Catch ex As Exception
MessageBox.Show("Problem with selection")
End Try
End Sub
and the new working code is as follows
Private Sub lvPCB1_DoubleClick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lvPCB1.DoubleClick
Dim newmachine As String = FrmSLE1000.txtNo.Text
Try
If lvPCB1.SelectedItems.Count = 0 Then
MessageBox.Show("Ensure that you have selected a PCB Board. Try again.")
Exit Sub
Else
'Set selected units ID number in varable to allow access to all row data to populate tables
selectedDeviceNumber = lvPCB1.SelectedItems(0).Text
PopulateTablesFunctionPCB()
txtSerialPCB1.Text = lvPCB1.SelectedItems(0).Text
'record activity in Activity Log
End If
Catch ex As Exception
MessageBox.Show("Problem with selection")
End Try
End Sub
So it all came down to having a "1" instead of a "0" in the line "txtSerialPCB1.Text = lvPCB1.SelectedItems(0).Text"
And there you have it!
I'm having a bit of an issue with my code. I have connected the database and am able to view records, add records and even delete records.
However, I cannot get the update button working at all. I keep getting an "InvalidOperationException" error.
Private Sub btnAmend_Click(sender As System.Object, e As System.EventArgs) Handles btnAmend.Click
Dim cb As New OleDb.OleDbCommandBuilder(da)
ds.Tables("Contacts").Rows(inc).Item(1) = txtFirstName.Text
ds.Tables("Contacts").Rows(inc).Item(2) = txtSurname.Text
da.Update(ds, "Contacts")
MsgBox("Data updated")
End Sub
On a form i have a listview with a contextmenu.
Right click on a listview item shows the context menu.
When i click on the menubutton, what i would like to happen is the following :
A form i called TaskLog will appear, it contains only a listview
(This is the code i have) :
Private Sub ShowLogToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ShowLogToolStripMenuItem.Click
logform = New TaskLog()
logform.task = "taskname"
logform.server = "servername"
logform.Show()
End Sub
That listview should be filled with data from a database before it shows, therefore i have the following in the load event of the TaskLog Form
Public Class TaskLog
Private db As Database = New Database
Public task As String
Public server As String
Private Sub TaskLog_Load(sender As Object, e As EventArgs) Handles MyBase.Load
db.connect()
db.getTaskLog(task, server, Me)
End Sub
End Class
Then in the database class gettask function i call the database, store data in an object, which all works fine. Only problem here is that my database object cannot find the listview and the form, even if i pass the form as a variable to this function (frm as TaskLog).
Public Function getTaskLog(taskname As String, server As String, frm As TaskLog) As Boolean
'Declare sql command variable
Dim command As New SqlCommand
'Try to open db connection
Try
connection.Open()
command.Connection = connection
'Set query to command object text
command.CommandText = "select * from tasklog where ltrim(rtrim(server)) Like'" & Trim(server) & "%' and ltrim(rtrim(task)) = '" & Trim(taskname) & "'"
'Declare data reading pbject
Dim rdr As SqlDataReader = command.ExecuteReader()
'Perform operations while rows are returned from database
While rdr.Read()
'Store database entry to TaskData Object
taskLogData = New TaskData(rdr("frequency").ToString, rdr("start"), rdr("duration"), rdr("delay"), rdr("rescheduled"), rdr("forced"), rdr("task"), rdr("server"), rdr("email"), rdr("message"), rdr("status"), rdr("logtime"))
Dim new_item As New _
ListViewItem(Trim(taskLogData.task_server.ToString))
new_item.SubItems.Add(Trim(taskLogData.task_name.ToString))
new_item.SubItems.Add(Trim(taskLogData.task_status.ToString))
new_item.SubItems.Add(Trim(taskLogData.task_frequency.ToString))
new_item.SubItems.Add(Trim(taskLogData.task_nextrun.ToString))
new_item.SubItems.Add(Trim(taskLogData.task_forced.ToString))
new_item.SubItems.Add(Trim(taskLogData.task_rescheduled.ToString))
new_item.SubItems.Add(Trim(taskLogData.task_rescheduled.ToString))
new_item.Group = frm.ListView1.Groups(Trim(taskData.task_status.ToString))
frm.ListView1.Items.Add(new_item)
End While
Return True
Catch ex As Exception 'If connection fails return error message
MessageBox.Show("Error while retrieving records on table..." & ex.Message, "Load Records")
Return True
Finally 'After connection close database
connection.Close()
End Try
End Function
Object Reference not set to an instance of an object appears on the following line in the function above:
frm.ListView1.Items.Add(new_item)
Can someone see the problem, and hopefully some help ? I tried a couple of things but still not sure about what to do best here. Thanks !!!!!!!
This line
new_item.Group = frm.ListView1.Groups(Trim(taskData.task_status.ToString))
refers to a Group that should exist in the ListView1. You could comment it out if it is not needed
I have a VB.NET 2010 application that loads data from SQL Server to a datagridview through adapter.fill(). When I update the database it works fine but my problem is that when i use the dataview to filter the data based on combobox selection the method adapter.update(table) does not work!
Is there away to do it with the filter applied?
Private Sub cmbDepartment_SelectedIndexChanged(...)
Handles cmbDepartment.SelectedIndexChanged
Dim filter As String
Try
lblDepartmentId.Text = ds.Tables("department").Rows(cmbDepartment.SelectedIndex)(0)
filter = "dprtId = " & lblDepartmentId.Text
dvSection = New DataView(ds.Tables("section"), filter, "", DataViewRowState.CurrentRows)
table = dvSection.ToTable
dgvSections.DataSource = table
Catch ex As Exception
MsgBox(Err.Description)
End Try
End Sub
Private Sub btnSaveDepartment_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles btnSaveDepartment.Click
Dim cbDep As SqlCommandBuilder
Dim numRows As Integer
Try cbDep = New SqlCommandBuilder(daDep)
Me.Validate() numRows = daDep.Update(ds.Tables("section"))
MsgBox(numRows & " Rows affected.")
Catch ex As Exception
MsgBox(Err.Description)
End Try
End Sub
The way you are currently doing your filtering is by creating a new DataTable and binding this to your DataGridView data source. This breaks the association between the original DataSet and that table so when you call Update your changes are not recovered.
Try changing to something like the code below instead (I've left out the try catch blocks, they don't change the idea that fixes your problem).
When you first set the data source to the grid set it to a form level private dvSection field:
Public Class Form1
' Here we declare some class level variables.
'These are visible to all members of the class
Dim dvSection As DataView
Dim tableAdapter As New DataSet1TableAdapters.CustomersTableAdapter()
Dim ds As New DataSet1()
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' We fill our dataset - in this case using a table adapter
tableAdapter.Fill(ds.Customers)
dvSection = ds.Customers.DefaultView
DataGridView1.DataSource = dvSection
End Sub
' Here is the code to filter.
' Note how I refer to the class level variable dvSection
Private Sub ComboBox1_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
Dim filter As String
lblDepartmentId.Text = ds.Tables("department").Rows(cmbDepartment.SelectedIndex)(0)
filter = "dprtId = " & lblDepartmentId.Text
dvSection.RowFilter = filter
dvSection.RowFilter = filter
End Sub
' And here is the update code referring to the class level table adapter
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
tableAdapter.Update(ds.Customers)
End Sub
End Class
One other approach that might make things easier is to introduce a binding source and set the filter on that. Either was should work fine however.