Logon fails if two tables are in the dataSet - vb.net

My report fills two tables. It works on the local server, but when published to another server it gives the following error:
Unable to connect. Login failed.
When I take off the second table and only use the first table, the report works. How can I resolve this?
objDataTable = New Data.DataTable
objDataTable.TableName = "Table"
objDataTable.Columns.Add("pes_nom", GetType(String))
objRow = objDataTable.NewRow
objRow("pes_nom") = objProposta.clsPessoa.pesNom
objDataTable.Rows.Add(objRow)
objDataSet = New Data.DataSet
objDataSet.Tables.Add(objDataTable)
If objProposta.clsDependente.DtDependentes IsNot Nothing Then
Dim dtCloned As New Data.DataTable
dtCloned = objProposta.clsDependente.DtDependentes.Clone()
dtCloned.Columns(3).DataType = System.Type.GetType("System.String")
For Each row As Data.DataRow In objProposta.clsDependente.DtDependentes.Rows
dtCloned.ImportRow(row)
Next
dtCloned.TableName = "Dependentes"
objDataSet.Tables.Add(dtCloned)
End If
Bmgviewer1.PathReport = "RptTermoAdesaoHAP.rpt"
Bmgviewer1.DataSet = objDataSet
Bmgviewer1.DataBind()

The solution was insert all data in just one table with multiple rows.
I added the following code:
If objProposta.clsDependente.DtDependentes IsNot Nothing Then
For Each row As Data.DataRow In objProposta.clsDependente.DtDependentes.Rows
objRow("dep_nom") = row.Item("dep_nom").ToString()
objRow("dep_cpf_cgc") = row.Item("dep_cpf_cgc").ToString()
objDataTable.Rows.Add(objRow)
objRow = objDataTable.NewRow
Next
Else
objDataTable.Rows.Add(objRow)
End If
And it worked.

Related

How to prevent adding repeated data into a listbox?

I have a bunch os items in lst1 which I want to put into lst2 but without repeating them on each ListBox.
Interface I'm using:
This is working, but you may need it to understand my doubt.
Dim dtTa_Enc As DataTable = New DataTable("Ta_Enc")
Dim dsTa As DataSet = New DataSet("Ta_E")
Dim adapter As New MySqlDataAdapter
Dim ds As DataSet = New DataSet
adapter.SelectCommand = New MySqlCommand
adapter.SelectCommand.Connection = connection
adapter.SelectCommand.CommandText = query
connection.Open()
adapter.Fill(ds, "tables")
connection.Close()
lst1.DataSource = ds.Tables("tables")
lst1.DisplayMember = "name"
lst1.ValueMember = "codta"
dtTa_Enc.Columns.Add("codta")
dtTa_Enc.Columns.Add("name")
dsTa.Tables.Add(dtTa_Enc)
lst2.DataSource = dsTa.Tables("Tables")
lst2.DisplayMember = "name"
lst2.ValueMember = "codta"
dtTa_Enc.Rows.Add(lst1.ValueMember, lst1.GetItemText(lst1.SelectedItem))
Doubt:
Now, The user presses a button to add his selected item of lst1 to lst2. Easy! However, what if he tries to add the same item. Can VB.Net stop him from doing it?
If not dtTa_Enc.find("codTa = " + lst1.valuemember) Then
dtTa_Enc.Rows.Add(lstTabelas.ValueMember, lstTabelas.GetItemText(lstTabelas.SelectedItem))
End If
Under the Add event handler, you could place some logic at the begining to prevent adding the repeated item.
Dim lst1Selected As String = CType(lst1.SelectedItem, DataRowView)("name").ToString
Dim flag As Integer = 0
For Each item As Object In lst2.Items
Dim istr As String = CType(item, DataRowView)("name").ToString
If istr = lst1Selected Then
flag = 1
Exit For
End If
Next
If flag = 1 Then
Exit Sub
End If
You can enumerate through your lst2 to determine whether any of the values match your selected item, lst1.SelectedItem.
So loop,
Dim found As Boolean = False
For Each itm As String in lst2.Items
If itm = lst1.SelectedItem Then
found = True
End If
Next
If Not found Then
'Add it.
End If
Or you can simply use the Contains method:
If Not lst2.Items.Contains(lst1.SelectedItem) Then
'Add it.
End if.

letting user type and add value to an already bound combobox

I have one combobox in my app that gets populated with a dozen or so items from SQL SERVER. I am currently trying to allow user to be able to type in a new value into the combobox and save it to a table in SQL SERVER. I'm looking for something along the lines of a DropDownStyle of DropDown and DropDownList. Basically I'm hoping to let the user type in the combobox, however if the value is not there, i want to be able to give them an option of saving it (probably on lost focus). I'm wondering what would be a good way of doing something like that.
On lost focus should I basically go through each item that is currently in the drop down and check it against the value entered?
EDIT:
Sql="SELECT IDvalue, TextName from TblReference"
Dim objconn As New SqlConnection
objconn = New SqlConnection(conn)
objconn.Open()
Dim da As New SqlDataAdapter(sql, objconn)
Dim ds As New DataSet
da.Fill(ds, "Name")
If ds.Tables("Name").Rows.Count > 0 Then
Dim dr As DataRow = ds.Tables("Name ").NewRow
ds.Tables("Name").Rows.InsertAt(dr, 0)
With c
.DataSource = ds.Tables("Name")
.ValueMember = " IDvalue "
.DisplayMember = " TextName "
End With
End If
You are already adding a fake/blank row to a table, you can do the same thing for a new item.
' form level datatable var
Private cboeDT As DataTable
Initializing:
cboeDT = New DataTable
Dim sql = "SELECT Id, Descr FROM TABLENAME ORDER BY Descr"
Using dbcon As New MySqlConnection(MySQLConnStr)
Using cmd As New MySqlCommand(sql, dbcon)
dbcon.Open()
cboeDT.Load(cmd.ExecuteReader())
' probably always need this even
' when there are no table rows (???)
Dim dr = cboeDT.NewRow
dr("Id") = -1 ' need a way to identify it
dr("Descr") = ""
cboeDT.Rows.InsertAt(dr, 0)
End Using
End Using
cboeDT.DefaultView.Sort = "Descr ASC"
cboE.DataSource = cboeDT
cboE.DisplayMember = "Descr"
cboE.ValueMember = "Id"
Note Users tend to have a preference as to the order of these things. The simple creatures tend to prefer alphabetical over a DB Id they may never see. To accommodate them, the DefaultView is sorted so that any new rows added will display in the correct order.
Add new items in the Leave event (much like Steve's):
Private Sub cboE_Leave(sender ...
' if it is new, there will be no value
If cboE.SelectedValue Is Nothing Then
' alternatively, search for the text:
'Dim item = cboeDT.AsEnumerable().
' FirstOrDefault(Function(q) String.Compare(q.Field(Of String)("Descr"),
' cboE.Text, True) = 0)
'If item Is Nothing Then
' ' its new...
Dim newid = AddNewItem(cboE.Text)
Dim dr = cboeDT.NewRow
dr("Id") = newid
dr("Descr") = cboE.Text
cboeDT.Rows.Add(dr)
' fiddling with the DS looses the selection,
' put it back
cboE.SelectedValue = newid
End If
End Sub
If you want to search by text:
Dim item = cboeDT.AsEnumerable().
FirstOrDefault(Function(q) String.Compare(q.Field(Of String)("Descr"),
cboE.Text, True) = 0)
If item Is Nothing Then
' its new...
...
Inserting will vary a little depending on the actual db. A key step though is to capture and return the ID of the new item since it is needed for the CBO:
Private Function AddNewItem(newItem As String) As Int32
Dim sql = "INSERT INTO MY_TABLE (Descr) VALUES (#v); SELECT LAST_INSERT_ID();"
Dim newId = -1
Using dbcon As New MySqlConnection(MySQLConnStr)
Using cmd As New MySqlCommand(sql, dbcon)
dbcon.Open()
cmd.Parameters.Add("#v", MySqlDbType.String).Value = newItem
' MySql provides it in the command object
If cmd.ExecuteNonQuery() = 1 Then
newId = Convert.ToInt32(cmd.LastInsertedId)
End If
End Using
End Using
Return newId
End Function
As noted MySql provides the LastInsertedID as a command object property. In SQL SERVER, tack ...";SELECT LAST_INSERT_ID();" to the end of your SQL and then:
newId = Convert.ToInt32(cmd.ExecuteScalar())
This is not conceptually very different from Steve's answer, except it uses the DataTable you build rather than collections which makes it (very) slightly simpler.
The way I do this, is on window load I perform a new SQL query to get the list of values in the table, and load them into a combobox.
Then once focus is lost, it then checks what's currently typed into the combobox against the current values already loaded. If it doesn't exist, then it's not in SQL. Something like the following...
Dim found As Boolean = False
For i As Integer = 0 To comboBox.Items.Count - 1
Dim value As String = comboBox.Items(i).ToString()
If comboBox.Text = value Then
found = True
End If
Next
If found = False Then
'the item doesn't exist.. add it to SQL
Else
'the item exists.. no need to touch SQL
End If
First thing I would do is to build a simple class to hold your values through a List of this class
Public Class DataItem
Public Property IDValue As Integer
Public Property TextName as String
End Class
Now, instead of building an SqlDataAdapter and fill a dataset, work with an SqlDataReader and build a List(Of DataItem)
' Class global...
Dim allItems = new List(Of DataItem)()
Sql="SELECT IDvalue, TextName from TblReference"
' Using to avoid leaks on disposable objects
Using objconn As New SqlConnection(conn)
Using cmd As New SqlCommand(Sql, objconn)
objconn.Open()
Using reader = cmd.ExecuteReader()
While reader.Read()
Dim item = new DataItem() With { .IDValue = reader.GetInt32(0), .TextName = reader.GetString(1)}
allItems.Add(item)
End While
End Using
if allItems.Count > 0 Then
allItems.Insert(0, new DataItem() With {.IDValue = -1, .TextValue = ""}
Dim bs = new BindingList(Of DataItem)(allItems)
c.DataSource = bs
c.ValueMember = "IDvalue"
c.DisplayMember = "TextName"
End If
End Using
End Using
Now the code that you want to add to your Leave event for the combobox
Sub c_Leave(sender As Object, e As EventArgs) Handles c.Leave
If Not String.IsNullOrEmpty(c.Text) Then
Dim bs = DirectCast(c.DataSource, BindingList(Of DataItem))
if bs.FirstOrDefault(Function(x) x.TextName = c.Text) Is Nothing Then
Dim item = new DataItem() With { .IDValue = -1, .TextName = c.Text}
bs.Add(item)
' here add the code to insert in the database
End If
End If
End Sub

IndexOutOfRangeException was unhandled VBNET

I have a form that retrieves the CurrentYearyear_now and NextYearyear_next from the database. It gives me the error 'IndexOutOfRangeException was unhandled' bcoz I think there is no row to be retrieved. And I wanted to do is, even though there's no data from the table, I can still load the forms and give me a null value to be displayed. I tried everything I know to make it work but I cant resolve the problem. Is there anyway to recode this.
Sub LoadSchoolYear()
Dim conn1 As New MySqlConnection("server=localhost; userid=root; password=root; database=uecp_cens")
Dim dAdapter1 As New MySqlDataAdapter("SELECT year_now, year_next FROM uecp_cens.tblschoolyear", conn1)
Dim dTable1 As New DataSet
Try
dAdapter1.Fill(dTable1, "uecp_cens")
lblYearNow.Text = dTable1.Tables("uecp_cens").Rows(0).Item(0).ToString
lblYearNext.Text = dTable1.Tables("uecp_cens").Rows(0).Item(1).ToString
Catch ex As MySqlException
MsgBox(ex.Message)
Finally
conn1.Dispose()
End Try
End Sub
Any help is appreciated.
If there is no row in the table as you've mentioned you get that error. So check Rows.Count:
Dim yearNow As String = Nothing
Dim yearNext As String = Nothing
If dTable1.Tables("uecp_cens").Rows.Count > 0 Then
yearNow = dTable1.Tables("uecp_cens").Rows(0).Item(0).ToString()
yearNext = dTable1.Tables("uecp_cens").Rows(0).Item(1).ToString()
End If
lblYearNow.Text = yearNow
lblYearNext.Text = yearNext
If instead the field is NULL in the DB it is DBNull.Value and you get an exception if you use Rows(0).Item(0).ToString(). Then use DataRow.IsNull to check it:
If dTable1.Tables("uecp_cens").Rows.Count > 0 Then
Dim row = dTable1.Tables("uecp_cens").Rows(0)
yearNow = If(row.IsNull(0), Nothing, row.Item(0).ToString())
yearNext = If(row.IsNull(1), Nothing, row.Item(1).ToString())
End If

datarow variable assign to dataset's table newrow

I'm trying to define a datarow to hold values and then add it to data set
indgv: datagridview with values in it
dsdetails: a dataset with a table named details
If indgv.Rows.Count > 0 Then
Dim dr As DataRow
dr = dsdetails.Tables("details").NewRow
For Each row As DataGridViewRow In indgv.Rows
dr("mat") = row.Cells("icode").Value
dr("dateoftrans") = Me.DateTimePicker1.Value
dr("numoftrans") = transnum.Text
dr("type") = 1
dr("doc") = doctyp.SelectedValue
dr("amount") = row.Cells("iamo").Value
dsdetails.Tables("details").Rows.Add(dr)
Next
adpdetails.Update(dsdetails, "details")
End If
running this causes the following error
Object reference not set to an instance of an object.
how to rephrase the declaration with 'New' to avoid the problen
BTW : when using new as the following
Dim dr As New DataRow = dsdetails.Tables("details").NewRow
it shows design time error
Type 'dsdetails.Tables' is not defined.
Try this code:
If indgv.Rows.Count > 0 Then
Dim tbl As DataTable = dsdetails.Tables("details")
Dim dr As DataRow
For Each row As DataGridViewRow In indgv.Rows
dr = tbl.NewRow 'Create a new row inside the loop!
dr("mat") = row.Cells("icode").Value
dr("dateoftrans") = Me.DateTimePicker1.Value
dr("numoftrans") = transnum.Text
dr("type") = 1
dr("doc") = doctyp.SelectedValue
dr("amount") = row.Cells("iamo").Value
tbl.Rows.Add(dr)
Next
adpdetails.Update(tbl)
End If
If all you need is to copy rows from one table to another, DataTable class has a Copy method you may want to use. It works like this:
Dim dtCopy As New DataTable()
dtCopy = dt.Copy()
If you have a datagridview control bound to a table, you could also use this form:
Dim dtCopy As New DataTable()
dtCopy = DirectCast(dataGridViewX1.DataSource, DataTable).Copy()
The Copy method will copy the datatable structure and the data.
If you want to copy the structure only without the data you could use Clone method.

For Each Next loop getting first row data only

I am trying to populate a dataset with data from a dynamic SQL dataset created by a code generator (PDSA). If I want the first row of data, or I use a specific "Where" clause to retrieve 1 row, I have no problem. But, when I loop through the dataset that has four entries, instead of getting the four entries, I get the first row 4 times. Any idea why?
Code Example:
Dim DS_C as New DS
Dim dr_A As DS_C.Tbl_ARow
Me.DS_C.Tbl_A.Clear()
Dim bo As PDSA.DataLayer.tbl_BDC = New PDSA.BusinessLayer.tbl_B
With bo
.ConnectionString = AppConfig.SQLConnectString
.SelectFilter = PDSA.DataLayer.tbl_BDC.SelectFilters.All
.WhereFilter = tbl_BDC.WhereFilters.None
.Load()
End With
For Each dr As DataRow In bo.DataSet.Tables(0).Rows
dr_A = DS_C.Tbl_A.NewRow
With dr_A
.CustomerID = bo.CustomerID
.FirstName = bo.FirstName
.LastName = bo.LastName
.Street = bo.Street
.City = bo.City
.State = bo.State
.ZipCode = bo.ZipCode
End With
DS_C.Tbl_A.AddTbl_ARow(dr_A)
Next
If I try to change it to use dr instead of bo , it wont accept it.
I get:
.CustomerID = dr.CustomerID(CustomerID is not a member of System.Data.DataRow)
If I try using DS_C.Tbl_ARow
For Each dr As DS_C.Tbl_ARow In bo.DataSet.Tables(0).Rows
I get type 'DS_C.Tbl_ARow' is not defined
If I try :
For Each dr As DS.Tbl_ARow In bo.DataSet.Tables(0).Rows
I get:
System.InvalidCastException = {"Unable to cast object of type 'System.Data.DataRow' to type 'TblXLMajorPerilsRow'."}
You need to access it like this:
.CustomerID = dr("CustomerID");