DataTable.GetChanges() is it possible to get rows by reference? - vb.net

Dim dtModifiedData As DataTable = dtMain.GetChanges(DataRowState.Modified)
As the definition of the function says, it does copy the rows after filtering it from the main table.
Is it possible to get them by reference?

Yes:
Dim modifiedRows = From row In dtMain.AsEnumerable()
Where row.RowState = DataRowState.Modified
If you need it in a DataTable, that's not possible because a DataRow always belongs to one DataTable. If you try to move it from one to another you'll get an exception. You need a method like ImportRow which creates a new DataRow with the values from the source-row. For the same reason CopyToDataTable on above LINQ query will also create new DataRows.

Related

how to bind datagridview to database at page load time in vb.net

I use below code in try catch block but it gives exception"'table' argument cannot be null. Parameter name: table" .My table name is caste and that table two columns are there srno and castename .But it say that my table has no data.Memory table is a datatable.
Dim Dset As New DataSet()
Dset = New DataSet()
Dset.Tables.Add(MemoryTable)
DataGridView1.DataSource = Dset.Tables("caste")
I tried data connect with database with using datasource but it gives service pack 1 error
'One is to use data binding on your TextBox controls and assigning the same DataSource.but its gives error
You don't show the definition of MemoryTable, but you do say it's a data table. If it's an object of type System.Data.DataTable, then it will have a property called TableName.
When you access a DataTable in a DataSet with a string index value, the value you are passing is the table's TableName property. So Dset.Tables("caste") is looking for a DataTable whose TableName property is set to "caste". If it can't find one, it will return Null. That looks like what's happening.
So set MemoryTable.TableName to "caste" and the error may go away.
I assume that MemoryTable actually has rows in it? If not, that may be a reason why you're getting the message about your table having no data.
So your code should look something like this:
Dim Dset As New DataSet() ' You don't have to do a separate assignment to Dset
' if you use New in the declaration, so we can omit that line.'
MemoryTable.TableName = "caste"
Dset.Tables.Add(MemoryTable)
DataGridView1.DataSource = Dset.Tables("caste")
And, actually, you can use MemoryTable as your data source without having to add it to a DataSet, unless you need to for some other reason.
DataGridView1.DataSource = MemoryTable
I hope this helps.

VB.Net Linq-to-datatable How to create a datatable based on an existing datable with filter

I have a similar issue like in this link,
Search DataTable with values from another table
Tim has given answer about this issue.
Dim strings = From row In PlTable Select row.Field(Of String)(0)
Dim found = From row In table.AsEnumerable
Where strings.Any(Function(s) row.Field(Of String)("Name").Contains(s))
Select row
Return found.CopyToDataTable()
Since I am new to this, so please help. In my P1Table, there are many values for the only one column. Do these codes return a new datatable for every value from P1Table? Also, in my P1Table, the ePlTable column has string values that are matched only first 3 characters of a column in the table. Do these codes still work? The last question, when I debug it, it shows the parameter "s" in Function(s) has only one character? Why? Thanks
Based upon what you wrote in your comments, although I'm very confused as to why you would want it this way and think you should rather look at your code a bit more and see if there's a nicer / neater solution (for example, using DataViews that automatically allow for filtering).
The way I would do this would look as follows:
Dim ReturnedTables As New List(Of DataTable)
Dim strings = From row In PlTable Select row.Field(Of String)(0)
For Each s As String In strings
Dim Retval = From row In table.AsEnumerable
Where row.Field(Of String)("Name").Contains(s)
Select row
If Retval.Count > 0 Then ReturnedTables.Add(Retval.CopyToDataTable)
Next
This will fill the variable ReturnedTables which will consist of separate DataTables as you mentioned wanting.
Again, note that this will be very memory intensive as you're actually creating a separate datatable for each iteration of the loop (rather than filtering), but it should do what you've requested.
Hope this helps!
Additional:
Based upon your question below, to get the number of rows from a specific datatable, it would look something long the lines of:
ReturnedTables(i).Rows.Count
And to get all the values from a specific field you would use the exact same syntax / logic as was used above to create the strings enumerable.
Hope that makes sense!!

what is this parameter in these SqlDataAdapter.Fill and DataSet.Tables

I have this part of code:
Dim SqlCommand_customer As New SqlCommand("selectcustomer", conn.con)
SqlCommand_customer.CommandType = CommandType.StoredProcedure
Dim da_customer As New SqlDataAdapter
Dim SqlDataAdapter_customer As New SqlDataAdapter(SqlCommand_customer)
Dim ds_customer = New DataSet()
SqlDataAdapter_customer.Fill(ds_customer, "customer")
DataGridView_customer.DataSource = ds_customer.Tables("customer")
So I want to know what does "customer" stands for in the last two lines
There is nothing named customer in the whole file
and MSDN states that the second parameter in Fill must be of type iDataReader:
dataReader
Type: System.Data.IDataReader
An instance of IDataReader.
The SqlDataAdapter class derives from DbDataAdapter that has a method overload for Fill that takes as second parameter a string.
This string is the name that will be assigned to the table created to store your records or, if you have already tables in the dataset, it is the name of a preexisting table wich will be loaded/refreshed with the records returned by the command.
Of course the syntax in
DataGridView_customer.DataSource = ds_customer.Tables("customer")
is the way in which you reference this table by its name (that would be the same as ds_customer.Tables(0))
The second argument to the fill command is the name of a table.
You are looking at the wrong reference. You want the Fill command off of the SQLDataAdapter.

Add row to datagridview in vb.net

When I try add an extra row to my datagridview I get following error:
Rows cannot be programmatically added to the DataGridView's rows collection when the control is data-bound.
Any idea to fix this, without databinding I added rows like this:
' Populate the rows.
Dim row() As String = {omschrijving, aantalstr, eenheidsprijs, basisbedrag, kortingstr, kortingbedrag, netto, btw, btwbedrag, totaal, productid}
DataGridView1.Rows.Add(row)
It looks like your grid view is bound to a data object. In that case, you need to add the row to the object it is bound to, like a dataset.
For instance, a rough example would be:
Dim boundSet As New DataSet
Dim newRow As DataRow = boundSet.Tables(0).NewRow
With newRow
.Item(0) = "omschrijving"
.Item(1) = "aantalstr"
...
End With
boundSet.Tables(0).Rows.Add(newRow)
boundSet.AcceptChanges()
You would just need to use the dataset that was bound to your grid view instead of creating a new one.

Fill Datatable using SQL 'select' WITHIN A TRANSACTION

I would like to fill a datatable with results from a SQL select statment but using a transaction. The reason that I am using a transaction is because I have a list of names (as a datatable), and I want to iterate through the list of names and select the database rows where the name = the name on the list. There are 500,000 names in the database and I only want to retreive the relevant rows. I have the code for the procedure as I think it should look like (untested) BUT I dont know HOW to place the data into a datatable .... so Im missing something where I declare the datatable and the 'fill' of that table , could someone help with this ? Or suggest how else I can get the information out of the batabase without looking up each name individually.
Using connection As New SQLite.SQLiteConnection(R2WconectionString)
connection.Open()
Dim sqliteTran As SQLite.SQLiteTransaction = connection.BeginTransaction()
Try
oMainQueryR = "SELECT NameID, Address, Ocupation FROM Employees Where Name= :Name"
Dim cmdSQLite As SQLite.SQLiteCommand = connection.CreateCommand()
With cmdSQLite
.CommandType = CommandType.Text
.CommandText = oMainQueryR
.Parameters.Add(":Name", SqlDbType.VarChar)
End With
'Prevent duplicate selects by using a dictionary
Dim NameInalready As New Dictionary(Of String, String)
For Each row As DataRow In TheLIST.Rows
If NameInalready.ContainsKey(row.Item("Name")) Then
Else
NameInalready.Add(row.Item("Name"), "")
cmdSQLite.Parameters(":Name").Value = row.Item("Name")
cmdSQLite.ExecuteNonQuery()
End If
Next
sqliteTran.Commit()
Catch ex As Exception
End Try
End Using
First, you don't need a transaction because you aren't updating the database.
Second, depending on the possible number of Names in TheLIST, it might be worthwhile for you to change the name selector to IN (i.e. SELECT * FROM Employees WHERE Name IN ('name1', 'name2'). However, if you expect more than about 10, this is probably not worth trouble.
Finally, you need to create a new DataTable to hold the results. Then you need to create a DataAdapter passing cmdSqlLite as the constructor parameter. And finally, replace your ExecuteNonQuery with DataAdapter.Fill(DataTable).
For example (after Dim cmdSQLite):
Dim oDataTable As New DataTable("Employees")
Dim oAdapter As New SqliteDataAdapter(cmdSQLite)
and replacing the ExecuteNonQuery line with:
oAdapter.Fill(oDataTable)
I will qualify this code by saying it may need some tweaks. I only work with class objects and collections, so my preference would have actually been to load a collection of Employee class instances.
I would have done that by replacing ExecuteNonQuery with ExecuteReader and then the loading the read data into a new class instance. This type of approach resolves various issues with serializing the data across service boundaries (i.e. Xml for web services) and also lets you embed business logic, if needed, into the classes.