I'm still pretty green when it comes to vb.net and programming in general, so I apologize ahead of time if this is general knowledge.
Scenario, I am dynamically creating the control's bindings, filling a datatable with my SQL tables Schema. At this point I want to be able to fill in my form and have those values populate my datatable.
So far my solution is to add a new datarow and then assign values to each field. This seems a little redundant because I already have the fields bound. Is there a trick to filling a datatable with values from a bound control?
What I am doing for binding:
boundSource.DataSource = myDataSet
boundSource.DataMember = myDataTablesName
me.ClientNumber.DataBindings.Add(New Binding("Text",boundSource, "Client_Number")
...
The above works fine when I populate the datatable form SQL, but when I am trying to add a new record I have to add the various control.values/text to the datatable.
I am using a sqlDataadapter with a commandbuilder to generate the Insert, Update and Delete. I believe the relevant code is:
Me.ValidateChildren()
bounndSource.EndEdit()
curCon.Open()
daClientMaster.Update(ds, "CLIENT_MASTER")
dt.AcceptChanges()
I would assume if I have 4 controls of varying types (text, date, etc.) and they are bound to specific fields in a datatable, that when I start the application I am starting on a new row of the datatable. So when I enter the information into the controls and then use the dataadapter update for said datatable, it would know to Insert. and really this is where the problem may lie. I am in way over my head, with too many task to accomplish, I have no time to fully understand anything I am doing (or maybe that's just programming in general.) If I am lacking an understanding of Databinding, or anything else, guidance to the correct information would be appreciated.
Thanks in advance
PC
Related
I have a dataview grid bound to a datasource at run time. The datasource is filled from an access database via a DataAdapter. The data fills and displays correctly, and updates to existing rows seem to work OK but I have two problems:
When I type something in a new row and then press return or switch to a different row, I want the DataAdapter to add that row then and there to the database so I can retrieve the Autonumber index of the new record from Access and use that to add an associated record in a different table (Entries, a many to many linking table). This isn't happening. In the RowLeave event I have adapter.Update(dsSentences) and then I check for the new row, but the RowCount doesn't reflect its presence even though the newly added data is visible in the grid, and the adapter.Update doesn't seem to have triggered the Insert query that I specified in the DataAdapter. So nothing is added.
(edit: OK, so the new row has not yet been added when this event is fired. Which event should I then use to commit the data and retrieve the Autonumber primary key for my new record? I've tried UserAddedRow but that one fires before you've entered any data into the new row.)
THe second problem is that I need to update the data independently and then have the grid reflect those changes. How do I do that? Is there some call that will force the grid to get the updated data from the DataAdapter via the Dataset? Any help would be much appreciated. I'm almost ready to dtop the whole idea of binding data and do it all through code, Data binfing is supposed to save time but I'm finding it labyrinthine and unpredictable.
FWIW here's the query I'm using to fill the grid:
PARAMETERS nIdCollection Long;
SELECT tblSentences.IdSentence, tblSentences.SentenceText, tblSentences.SentenceParsed, Not IsNull([tblSentences]![SentenceParsed]) AS HasParsed, Entries.IdEntry
FROM tblSentences INNER JOIN Entries ON tblSentences.IdSentence = Entries.IdSentence
WHERE (((Entries.IdCollection)=[nIdCollection]))
ORDER BY Entries.SortValue;
As you can see, it requires a record in Entries. After I've entered a new record in tblSentences, before there are any entries the IdEntry will be null assuming it shows up at all. That's why I need to intercept directly after the Insert, add the record to Entries and requery to keep everything in order. You could do it all in an SQL stored procedure but I have to use Access.
Edit: After a lot of googling I've come to the conclusion that what I'm trying to do = add a record to a table through an additional INSERT query apart from the one handled by the DataAdapter, every time a new row is added - simply can't be done if you are using data binding. I am going to have to delete all my code and start from scratch populating the grid through code (unbound). I think it's the only way to do what I want. I will leave this here as a warning to anyone else not to make my mistake of trying to use Data binding when your data is coming from more than one table. Bad mistake.
I want to populate a DataGridView Grid in my Form with Data from SQL Query or from some Table form Database. I want to know various possible ways to populate the DataGridView Grid.
Thanks in advance.
There are basically 3 ways to display data in a DataGridView
Create the rows manually in a loop: it's very inefficient if you have a lot of data
Use the DataGridView's virtual mode: the DGV only creates as many rows as can be displayed, and
dynamically changes their contents when the user scrolls. You need
to handle the CellValueNeeded event to provide the required data to
the DGV
Use databinding: that's by far the easiest way. You just fill a
DataTable with the data from the database using a DbDataAdapter, and
you assign this DataTable to the DGV's DataSource property. The DGV
can automatically create the columns (AutoGenerateColumns = true),
or you can create them manually (you must set the DataPropertyName
of the column to the name of the field you want to display). In
databound mode, the DGV works like in virtual mode except that it
takes care of fetching the data from the datasource, so you don't
have anything to do. It's very efficient even for a large number of
rows
Link.
Forgive me for this seemingly obvious question, but my searches have not revealed the answer.
I have a DataGridView bound to a DataTable. Although all rows are displayed in the grid, the table represented by the Grid's DataSource does not get updated after changing values in one or more DataGridView columns. Both grid and table contain a Primary Key. What am I missing here? Do I need to do something in the RowValidated event?
dgvCriticalContacts.AutoGenerateColumns = False
Dim ccRs As DataTable = Common.OpenRecordset("SELECT * FROM PhoneList")
dgvCriticalContacts.DataSource = ccRs
A DataGridView does not have the ability to automatically update the database you are getting your information from. While you can use a DataTable to give the DataGridView a data source, it also does not have the ability to update itself back to the database.
However, the .Net Framework does have a TableAdapter ( http://msdn.microsoft.com/en-us/library/bz9tthwx%28v=vs.90%29.aspx, 3.5 and earlier) or a DataAdapter ( http://msdn.microsoft.com/en-us/library/system.data.common.dataadapter%28v=vs.90%29.aspx, All versions) that can perform these functions.
My personal experience is that these adapters very quickly cause more problems than they solve if it is anything more a simple data structure. If it is anything more complex, you are better off creating a class for your rows and making a BindingList (or something similar) to allow the DataGridView to display them. You will have to implement your own change tracking and CRUD statements, but it's well worth it and will likely cause less of a headache in the long run.
I used the DataSet Designer to create FTWDataSet which holds the AlarmText table from a SQLExpress database. This far my form contains ONLY Datagridview1. The code below successfully shows the contents of the AlarmText table plus the one added checkbox column (which I will populate with display-only data, and is not an issue here).
Dim ta As New FTWDataSetTableAdapters.AlarmTextTableAdapter
Dim dt As New FTWDataSet.AlarmTextDataTable
ta.Fill(dt)
DataGridView1.DataSource = dt
'create a new Bool column in the datatable
dt.Columns.Add("NewCol", (New Boolean).GetType)
What else do I need to do to use the DataGridView to edit and save values in the AlarmText table?
Here's a brief MSDN walkthrough on this topic.
Some notes:
You shouldn't need a binding source to persist changes back to the database.
To make the table adapter accessible to other procedures in your form, make it a form-scoped (a.k.a. member) variable instead of method-scoped, as in your example.
If you created your Dataset using the Dataset Designer, and you're fetching your original data from anything more than a simple table or view, then your adapter won't know how to update anything in the original database. You have to manually configure the UPDATE command in this situation. For reference, see the TableAdapter Update Commands section in the above link.
I should also mention that I avoid TableAdapters in ADO.Net like the plague. In theory they're very convenient and powerful. In practice, many of them (especially the one for the Oracle provider) are buggy, and if they don't work exactly right you're totally screwed.
If you're pulling from just one underlying table, the adapter should work fine (so ignore my nihilistic advice for the time being). It may be that adding an additional column in code will breaks the adapter (since there's no corresponding column in the database table).
I've done development in both VB6 and VB.NET, and I've used ADODB objects in VB6 to handle recordset navigation (i.e. the MoveFirst, MoveNext, etc. methods), and I have used ADO.NET to handle queries in a row-by-row nature (i.e For Each Row In Table.Rows ...)
But now I seem to have come to a dilemma. I am now building a program in VB.NET where I need to use the equivalent functionality of the Move commands of the old Recordset object. Does VB.NET have some sort of object that supports this functionality, or do I have to resort to using the old ADODB COM object?
Edit: Just for clarification, I want the user to be able to navigate through the query moving forwards or backwards. Looping through the rows is a simple task.
There is no need to go back to the bad old days. If you can give a pseudo code example, I can translate to vb.net for you.
This is kind of a generic way to do it.
Dim ds as DataSet
'populate your DataSet'
For each dr as DataRow in ds.Tables(<tableIndex>).Rows
'Do something with the row'
Next
Per Edit 1: The user will navigate the results, not the query. So what you want to do is either a) get the results and display only the current rowindex of ds.Tables.Row() to them, or b) execute a new query with each navigation (not a real well performing option.)
Per comment: No, they havent. But the user usually will not be working interactively with the database like this. You will need to get your dataset / table of the results, and use the buttons to retrieve the relevant row from the dataset/table.
The First Row is DataTable.Rows(0)
The Last Row is DataTable.Rows(DataTable.Rows.Count-1)
for any row in between (store the currently displayed rowindex in your app), then call
DataTable.Rows(currentRowIndex -1) for previous and
DataTable.Rows(currentRowIndex +1) for next.
It all depends on the usage:
If you need only to list the results of one or more queries you should use the datareader. Has DOK pointed out, it's read-only and foward-only so it's fast.
http://www.startvbdotnet.com/ado/sqlserver.aspx
If you need to navigate thou the records you should use a dataset.
http://www.c-sharpcorner.com/UploadFile/raghavnayak/DataSetsIn.NET12032005003647AM/DataSetsIn.NET.aspx
The dataset also has the advantage of working "disconnected", so you build all the logic, and only when you need the data you call the Fill method. The dataset is populated and then you can start working with the data, now disconnected from the DB.
Hope it helps,
Bruno Figueiredo
http://www.brunofigueiredo.com
Here's a quick example of using the datareader:
Dim cmd As New OleDb.OleDbCommand(sql, Conn) 'You can also use command parameter here
Dim dr As OleDb.OleDbDataReader
dr = cmd.ExecuteReader
While dr.Read
‘Do something with data
‘ access fields
dr("fieldname")
‘Check for null
IsDBNull(dr("fieldname"))
End While
dr.Close()
In .Net, there are many ways to do this. One that I like is to use a DataReader, which can return multiple recordsets. You can loop through its records using While DataReader.Read.
One of the advantages of using DataReader is that it is a forward-only, read-only object, so it's fast and light-weight.
To allow the user to navigate through all of the records, one at a time, you do not want to hold a DataReader open while the user navigates. you can read the DataReader records into objects. Or, you can retrieve the records into a DataSet, and display the DataRows from the DataTable one at a time.
I would suggest that, if possible, you retrieve all of the records at once if there are not too many. This will save repeated calls to the database.
On the other hand, if there are a lot of records, you could retrieve the first few (say, 10 or 20) and only retrieve the next set of records with a new database call if the user clicks beyond the initial set. This is lazy loading.