sqldependency on change not always firing - vb.net

Here is my code:
Public Sub RegisterNotification()
Dim conStr As String = ConfigurationManager.ConnectionStrings("sqlConString").ConnectionString
Dim sqlCommand As String = "SELECT [ID],[Description], [CreateDate], [NoteTypeID] from [note].[Notes]"
Using con As New SqlConnection(conStr)
Dim cmd As New SqlCommand(sqlCommand, con)
If con.State <> System.Data.ConnectionState.Open Then
con.Open()
End If
cmd.Notification = Nothing
Dim sqlDep As New SqlDependency(cmd)
AddHandler sqlDep.OnChange, AddressOf sqlDep_OnChange
Using reader As SqlDataReader = cmd.ExecuteReader()
End Using
End Using
End Sub
Private Sub sqlDep_OnChange(sender As Object, e As SqlNotificationEventArgs)
If e.Type = SqlNotificationType.Change Then
Dim sqlDep As SqlDependency = TryCast(sender, SqlDependency)
'Dim id
RemoveHandler sqlDep.OnChange, AddressOf sqlDep_OnChange
If e.Info = 1 Then
Dim notificationHub = GlobalHost.ConnectionManager.GetHubContext(Of NotificationHub)()
notificationHub.Clients.All.notify("added")
RegisterNotification()
'GetNotificationList(0, 1)
End If
End If
End Sub
Global.asax code:
Protected Sub Application_Start()
Try
Dim _obj As New DAL.sap.Register
_obj.Register()
AreaRegistration.RegisterAllAreas()
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters)
RouteConfig.RegisterRoutes(RouteTable.Routes)
BundleConfig.RegisterBundles(BundleTable.Bundles)
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "webpages_UserProfile", "UserId", "UserName", True)
SqlDependency.Start(con)
Catch ex As Exception
End Try
End Sub
Protected Sub Session_Start(sender As Object, e As EventArgs)
Try
Dim NC As New NotificationComponent()
NC.RegisterNotification()
Catch ex As Exception
End Try
End Sub
Protected Sub Application_End()
Try
SqlDependency.Stop(con)
Catch ex As Exception
End Try
End Sub
Startup code:
<Assembly: OwinStartupAttribute(GetType(www.Startup))>
Namespace www
Partial Public Class Startup
Public Sub Configuration(app As IAppBuilder)
app.MapSignalR()
End Sub
End Class
End Namespace
My problem is sqldep_onchange not always firing. Sometimes it works perfectly but sometimes nothing happen. is it a bug or something like that? what i'm doing wrong?

It looks like everything is correct, although my VB is extremely rusty, I would try removing the if on the SqlNotificationType and see if that helps, it might be too restricting, I would also make sure that its actually the dependency that is not firing rather an something else swallowing it later on down the chain. Also what happens if your TryCast fails? Since its not in a try it will not throw and your notifications will not fire and your new handler will not be added.
Private Sub sqlDep_OnChange(sender As Object, e As SqlNotificationEventArgs)
If e.Type = SqlNotificationType.Change Then
Dim sqlDep As SqlDependency = TryCast(sender, SqlDependency)
'Dim id
Delete --> ***RemoveHandler sqlDep.OnChange, AddressOf sqlDep_OnChange*** <--Delete
If e.Info = 1 Then
Dim notificationHub = GlobalHost.ConnectionManager.GetHubContext(Of NotificationHub)()
notificationHub.Clients.All.notify("added")
RegisterNotification()
'GetNotificationList(0, 1)
End If
End If
End Sub

Related

Need help editing Customer Info in VB.net

I am trying to edit customers using my C# project to learn how to implement this code in VB.net. The project was successful in adding customers, but when it got to editing customers, things got a bit more complicated because I needed to get the id of the row selected and pass it to a string. I have the MainForm.vb which could open CustomerForm.vb when I click on 'Edit'. When CustomerForm.vb opens, it failed to show the customer's info. I am not sure if FillDataTable() function is necassary, I would like to know if there is an improvement to this.
CustomerForm.vb
Imports System.Data.SqlClient
Public Class CustomerForm
Private objConnection As SqlConnection
Public objDataTable As DataTable = New DataTable()
Public objSqlCommand As SqlCommand = New SqlCommand()
Public editMode As Boolean = False
Public id As String = ""
Public FName As String = ""
Public LName As String = ""
Public PhNumber As String = ""
Public ReadOnly Property Connection As SqlConnection
Get
Return Me.objConnection
End Get
End Property
Dim CS As String = ("server=CASHAMERICA;Trusted_Connection=yes;database=ProductsDatabase2; connection timeout=30")
Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click
Try
If editMode = False Then
If txtFirstName.Text = "" Then
MessageBox.Show("First Name Is required")
ElseIf txtLastName.Text = "" Then
MessageBox.Show("Last Name Is required")
Else
Dim con As New SqlConnection(CS)
con.Open()
Dim cmd As New SqlCommand("INSERT INTO Customers(FIrstName,LastName,PhoneNumber) VALUES(#FName, #LName, #PhNumber)", con)
cmd.Parameters.AddWithValue("#FName", txtFirstName.Text)
cmd.Parameters.AddWithValue("#LName", txtLastName.Text)
cmd.Parameters.AddWithValue("#PhNumber", txtPhoneNumber.Text)
cmd.ExecuteNonQuery()
MessageBox.Show("Customer has been added!")
con.Close()
End If
ElseIf editMode = True Then
If txtFirstName.Text = "" Then
MessageBox.Show("First Name Is required")
ElseIf txtLastName.Text = "" Then
MessageBox.Show("Last Name Is required")
Else
Dim con As New SqlConnection(CS)
con.Open()
Dim cmd As New SqlCommand("UPDATE Customers SET FIrstName = #FName, LastName = #LName, PhoneNumber = #PhNumber WHERE Id = #Id", con)
cmd.Parameters.AddWithValue("#Id", id)
cmd.Parameters.AddWithValue("#FName", txtFirstName.Text)
cmd.Parameters.AddWithValue("#LName", txtLastName.Text)
cmd.Parameters.AddWithValue("#PhNumber", txtPhoneNumber.Text)
cmd.ExecuteNonQuery()
MessageBox.Show("Customer has been edited.")
con.Close()
End If
End If
Catch ex As Exception
MessageBox.Show(Me, ex.Message, "Save Failed", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End Sub
Private Sub btnCancel_Click(sender As Object, e As EventArgs) Handles btnCancel.Click
Me.Close()
End Sub
Private Sub CustomerForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
If editMode = False Then
GetId()
Else
textId.Text = id
txtFirstName.Text = FName
txtLastName.Text = LName
txtPhoneNumber.Text = PhNumber
End If
End Sub
Private Sub GetId()
Dim con As New SqlConnection(CS)
con.Open()
Dim cmd As New SqlCommand("SELECT MAX(id)+1 FROM Customers")
textId.Text = FillDataTable().Rows(0)(0).ToString()
If textId.Text = "" Then
textId.Text = "1"
End If
End Sub
Public Property CommandText As String
Get
Return CommandText
End Get
Set(ByVal value As String)
CommandText = value
End Set
End Property
Public Sub OpenDBConnection()
objConnection = New SqlConnection(CS)
objConnection.Open()
End Sub
Public Sub CreateCommandObject()
objSqlCommand = objConnection.CreateCommand()
objSqlCommand.CommandText = CommandText
objSqlCommand.CommandType = CommandType.Text
End Sub
Public Function FillDataTable() As DataTable
objDataTable = New DataTable()
objSqlCommand.CommandText = CommandText
objSqlCommand.Connection = objConnection
objSqlCommand.CommandType = CommandType.Text
objDataTable.Load(objSqlCommand.ExecuteReader())
objConnection.Close()
Return objDataTable
End Function
Public Sub CloseConnection()
If objConnection IsNot Nothing Then objConnection.Close()
End Sub
End Class
MainForm.vb
Imports System.Windows.Forms.LinkLabel
Public Class MainForm
Private Sub ExitToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ExitToolStripMenuItem.Click
Me.Close()
End Sub
Private Sub AddToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles AddToolStripMenuItem.Click
CustomerForm.ShowDialog()
End Sub
Private Sub AddToolStripMenuItem1_Click(sender As Object, e As EventArgs) Handles AddToolStripMenuItem1.Click
ProductForm.ShowDialog()
End Sub
Private Sub ViewProductsToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ViewProductsToolStripMenuItem.Click
ManageProductsForm.ShowDialog()
End Sub
Private Sub AboutToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles AboutToolStripMenuItem.Click
AboutForm.Show()
End Sub
Private Sub MainForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'TODO: This line of code loads data into the 'ProductsDatabase2DataSet1.Customers' table. You can move, or remove it, as needed.
Me.CustomersTableAdapter.Fill(Me.ProductsDatabase2DataSet1.Customers)
End Sub
Private Sub gridCustomers_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles gridCustomers.MouseUp
Try
Dim f As CustomerForm = New CustomerForm()
f.editMode = True
Dim rowIndex As Integer = gridCustomers.CurrentCell.RowIndex
f.id = gridCustomers.Rows(rowIndex).Cells("colId").Value.ToString()
f.FName = gridCustomers.Rows(rowIndex).Cells("colFirstName").Value.ToString()
f.LName = gridCustomers.Rows(rowIndex).Cells("colLastName").Value.ToString()
f.PhNumber = gridCustomers.Rows(rowIndex).Cells("colPhoneNumber").Value.ToString()
f.Show()
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
Private Sub gridCustomers_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles gridCustomers.CellContentClick
Dim f As CustomerForm = New CustomerForm()
f.ShowDialog(Me)
f.editMode = True
End Sub
End Class
Error Message:
Customer Info not displayed:
As mentioned, it seems like you have several things potentially going on.
The first thing I would change is your public sql objects. You don't need them to be public. It also increases the chances for issues if you're using the same objects in multiple places.
SqlCommand, SqlConnection, and SqlDataAdapters can be immediately disposed of (in most cases) as soon as they are used.
One easy method to handling all of that is to throw everything inside of a USING block.
Dim sqlResult As New Datatable()
Using cn As New SqlConnection("Connection String here"),
cmd As New SqlCommand(sql, cn),
adapt As New SqlDataAdapter(cmd)
cn.Open()
'Handle stored procedure vs select options
If sql.Contains("SELECT") Then
cmd.CommandType = CommandType.Text
Else
cmd.CommandType = CommandType.StoredProcedure
End If
'If parameters passed, else comment out
cmd.Parameters.AddWithValue("#parameterName", parameterValue)
sqlResult = New DataTable(cmd.CommandText)
adapt.Fill(sqlResult)
End Using
Now all your objects are disposed of as soon as your datatable is filled.
*This example uses a datatable, but it is the same idea for anything interacting with sql objects.
If implemented, you may find out that some objects weren't being disposed of or initialized properly.
Another method for testing where things are going wrong is to query the states of the SQL objects before or around the error to see if something isn't set correctly or is uninitialized.

Run two events simultaneously

The code for my animated text already stored in my Table1 works very well without any error in my MDIParent1.But when I execute another code for exemple an print code when i click on Button_Print The animated text will stop Temporary and the animation of the text will be very heavy.Please How to run other code without effect on my animated text ?
My code in Module1
Public Sub Text_Panel_Animation()
Try
Dim da As New OleDbDataAdapter("Select * from Table1 order by Id", Con)
Dim dt As New DataTable
da.Fill(dt)
MDIParent1.Label1.Left = 0 - MDIParent1.Label1.Width
If dt.Rows.Count > 0 Then
For r As Integer = 1 To dt.Columns.Count - 1
MDIParent1.Label1.Text &= " " & (dt(0)(r).ToString)
Next
MDIParent1.Timer1.Start()
End If
Con.Close()
Catch ex As Exception
MsgBox(ex.Message(), MsgBoxStyle.Critical, "Error")
End Try
End Sub
In MDIParent1 Load .. I put this code :
Call Text_Panel_Animation()
And In MDIParent1 .. i have also :
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
If Label1.Left >= Me.Panel1.Width Then Label1.Left = 0 - Label1.Width
Label1.Left += 1
End Sub
I tried with this code but i have a same problem :
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Task.Run(Sub()
Try
Dim Dt As New DataTable
Dim SQLstr As String = "Select * from Table1"
SQLstr = "Select * from Table1 order BY Id"
Dim Da As New OleDbDataAdapter(SQLstr, Con)
Da.Fill(Dt)
Dim Rpt As New Crystal1
Rpt.SetDataSource(Dt)
Dim frm As New Form1
Me.Dispose()
frm.Show()
Form1.CrystalReportViewer1.Zoom(100%)
Catch
End Try
End Sub)
End Sub
You can start the printing in a new task
Private Sub Button_Print_Click (sender As Object, e As EventArgs) Handles Button_Print.Click)
Task.Run(Sub()
'TODO: Do the printing here...
End Sub)
End Sub
Note that you have to take precautions to be able to access the UI from this other task. See: VB.NET: Invoke Method to update UI from secondary threads
I would not do any UI stuff in the other task, since this can lead to problems. Instead, I would only query the DB and render the report in another task and then await this task before doing UI-related things. I'm not using Crystal Reports myself, but it would probably be something like this
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim Rpt As Crystal1
Await Task.Run(
Sub()
Try
Dim Dt As New DataTable
Dim SQLstr As String
SQLstr = "Select * from Table1 order BY Id"
Dim Da As New OleDbDataAdapter(SQLstr, Con)
Da.Fill(Dt)
Rpt = New Crystal1
Rpt.SetDataSource(Dt)
Catch
End Try
End Sub)
Dim frm As New Form1
Me.Dispose()
frm.Show()
Form1.CrystalReportViewer1.Zoom(100%)
Form1.CrystalReportViewer1.ReportSource = Rpt
End Sub
Do not forget the Async keyword in the method header.
Note: If Me is the main form, then Me.Dispose() will terminate the application.

Passing variable to ComboBox method

I have a variable that is being passed from my first form, to my second form. However, when I try to use this variable inside my ComboBox event handler method, it's showing up blank and I can't figure out why.
Public CellValue As String
Public Sub New(ByVal CellValue As String)
InitializeComponent()
MsgBox(CellValue)
End Sub
This works just fine, I am able to bring up the messagebox with the Cell Value. However, when I try to access this CellValue in my combo box method that is on the same Form, the variable is blank, and I can't figure out why.
Public Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
MsgBox(CellValue)
End Sub
I've tried putting the "ByVal CellValue As String" as an argument in the combobox but that does not work, I get an error that it can not handle the event.
I have the variable set as public so I don't understand what is going on. Any help in the right direction would be great because I have been searching the net for hours.
Here is the Form1 if that helps:
Imports MySql.Data.MySqlClient
Public Class Form1
Dim MysqlConn As MySqlConnection
Dim COMMAND As MySqlCommand
Dim value As String
Private Sub Label1_Click(sender As Object, e As EventArgs) Handles Label1.Click
End Sub
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
MysqlConn = New MySqlConnection
MysqlConn.ConnectionString = "server=0.0.0.0;
userid=username;
password=******;
database=password"
Dim SDA As New MySqlDataAdapter
Dim dbDataSet As New DataTable
Dim bSource As New BindingSource
Try
MysqlConn.Open()
Dim Query As String
Query = "select CaseNumber, FirstName, LastName from customer"
COMMAND = New MySqlCommand(Query, MysqlConn)
SDA.SelectCommand = COMMAND
SDA.Fill(dbDataSet)
bSource.DataSource = dbDataSet
DataGridView1.DataSource = bSource
SDA.Update(dbDataSet)
MysqlConn.Close()
Catch ex As MySqlException
MessageBox.Show(ex.Message)
Finally
MysqlConn.Dispose()
End Try
End Sub
Public Sub DataGridView1_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellContentClick
If e.ColumnIndex = 0 Then
Dim CellValue As Object = DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value
If IsDBNull(value) Then
MsgBox("No Case Number for this particular record.")
Else
Dim ThirdForm As New Form2(CellValue)
Me.Hide()
ThirdForm.Show()
End If
End If
End Sub
End Class
The following worked for me thanks to Plutonix in comment section. Thank you.
Me.CellValue = CellValue

How to download from ftp without form lag vb.net

I just made a ftp chat in vb.net and it update message from a file from a ftp server
so i add a timer with interval 1000 with this code
Try
Dim client As New Net.WebClient
client.Credentials = New Net.NetworkCredential("fnet_1355****", "******")
RichTextBox1.Text = client.DownloadString("ftp://185.**.***.**/htdocs/chat­.txt")
Catch ex As Exception
End Try
so .. the file is downloaded and it update the text successful but there is a problem .. every time he download the form have a bit lag ... and i dont like that :D what i can do ?
RichTextBox1.Text = client.DownloadString("ftp://185.**.***.**/htdocs/chat­.txt")
Instead of this try async method.
client.DownloadStringAsync(new Uri("ftp://185.**.***.**/htdocs/chat­.txt"))
and then handle download string completed event.
Sample Code
client.DownloadStringAsync(new Uri("ftp://185.**.***.**/htdocs/chat­.txt"));
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
RichTextBox1.Text =e.Result;
}
You can also add progress indicator by handling progress change event.
The best way you can do it would be to use ThreadPool provided by the Framework to I/O bound operation on different thread.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf DownloadFromFtp))
End Sub
Private Sub DownloadFromFtp()
Try
Dim client As New Net.WebClient
client.Credentials = New Net.NetworkCredential("fnet_1355****", "******")
Dim response As String = client.DownloadString("ftp://185.**.***.**/htdocs/chat­.txt")
Me.Invoke(New MethodInvoker(Function() RichTextBox1.Text = response))
Catch ex As Exception
End Try
End Sub
This program was the exact one I design before i learned PHP.
Here try this:
Dim thrd As Threading.Thread
Dim tmr As New Timer
Dim tempstring As String
Private Sub thread_start()
thrd = New Threading.Thread(Sub() check_for_changes())
tmr.Interval = 50
AddHandler tmr.Tick, AddressOf Tick
tmr.Enabled = True
tmr.Start()
thrd.Start()
End Sub
Private Sub Tick(sender As Object, e As EventArgs)
If Not thrd.IsAlive Then
tmr.Stop() : tmr.Enabled = False
RichTextBox1.Text = tempstring
End If
End Sub
Private Sub check_for_changes()
Try
Dim client As New Net.WebClient
client.Credentials = New Net.NetworkCredential("fnet_1355****", "******")
tempstring = client.DownloadString("ftp://185.**.***.**/htdocs/chat­.txt")
Catch ex As Exception
End Try
End Sub
Hope It Helps.

Form.show() does not respond

I am writing a small postIt programm which should enable the user to send little notes to other computers using a database.
I have a main-Form where I can write messages and see users online, a sheet-form which should display messages and a sql database which has a table for users and messages.
The idea is that I am writing messages into the Messagestable and my programm uses SqlDependency to get the new messages and to show them in sheets. So far so good.
The problem is when I add a new Message to my table the SqlDependency fires an Event and my mainForm creates a new sheet which freezes after sheet.Show() is called. The mainForm keeps on running but my sheets always do not respond.
Here's my code:
DBListener:
Imports System.Data
Imports System.Data.Sql
Imports System.Data.SqlClient
Imports System.Threading
Public Class DBListener
Private changeCount As Integer = 0
Private Const tableName As String = "IMSMessages"
Private Const statusMessage As String = _
"{0} changes have occurred."
Private exitRequested As Boolean = False
Private waitInProgress As Boolean = False
Private recieverHost As String
Private imsMain As IMSMain
Public Sub New(main As IMSMain, recieverHost As String)
Me.imsMain = main
Me.recieverHost = recieverHost
initCommand(recieverHost)
SqlDependency.Start(connectionString)
GetMsg(recieverHost)
End Sub
Private connectionString As String = "Data Source=NB_RANDY\SQLEXPRESS;Initial Catalog=eurom_test;Integrated Security=SSPI;"
Private sqlConn As SqlConnection = New SqlConnection(connectionString)
Private commandMesg As SqlCommand = Nothing
Private commandUsers As SqlCommand = Nothing
Private Sub initCommand(recieverHost As String)
commandMesg = New SqlCommand
commandMesg.CommandText = "SELECT MessageID,SenderHost,RecieverHost,isRead,isRecieved,Stamp from dbo.IMSMessages " &
"WHERE RecieverHost=#RecieverHost" &
" AND isRecieved = 0"
commandMesg.Parameters.Add("#RecieverHost", SqlDbType.VarChar).Value = recieverHost
commandMesg.Connection = sqlConn
commandUsers = New SqlCommand
commandUsers.CommandText = "Select HostName From dbo.IMSUser"
End Sub
Private Sub OnChangeMsg(ByVal sender As System.Object, ByVal e As System.Data.SqlClient.SqlNotificationEventArgs)
Dim dep As SqlDependency = DirectCast(sender, SqlDependency)
RemoveHandler dep.OnChange, AddressOf OnChangeMsg
GetMsg(recieverHost)
End Sub
Private Sub OnChangeUser(ByVal sender As System.Object, ByVal e As System.Data.SqlClient.SqlNotificationEventArgs)
Dim dep As SqlDependency = DirectCast(sender, SqlDependency)
RemoveHandler dep.OnChange, AddressOf OnChangeUser
GetUsers()
End Sub
Public Sub GetMsg(recieverHost As String)
If Not sqlConn.State = ConnectionState.Open Then
sqlConn.Open()
End If
commandMesg.Notification = Nothing
Dim dep As SqlDependency = New SqlDependency(commandMesg)
AddHandler dep.OnChange, New OnChangeEventHandler(AddressOf OnChangeMsg)
Dim table As DataTable = New DataTable
Dim adapter As SqlDataAdapter = New SqlDataAdapter(commandMesg)
adapter.Fill(table)
imsMain.recieveNewMessages(table)
End Sub
Public Sub GetUsers()
If Not sqlConn.State = ConnectionState.Open Then
sqlConn.Open()
End If
commandMesg.Notification = Nothing
Dim dep As SqlDependency = New SqlDependency(commandUsers)
AddHandler dep.OnChange, New OnChangeEventHandler(AddressOf OnChangeUser)
Dim table As DataTable = New DataTable
imsMain.updateOnlineUserList()
End Sub
End Class
IMSMain-Form:
Imports System.Data.SqlClient
Imports System.Threading
Public Class IMSMain
Private user As IMSUser
Private listener As DBListener
Private sqlConn As SqlConnection
Public Sub New()
InitializeComponent()
sqlConn = New SqlConnection("Data Source=NB_RANDY\SQLEXPRESS;Initial Catalog=eurom_test;Integrated Security=SSPI;")
Me.user = New IMSUser(My.Computer.Name)
user.register()
updateOnlineUserList()
listener = New DBListener(Me, user.HostName)
End Sub
Private Sub onSend(sender As Object, e As EventArgs) Handles bt_send.Click
Dim command As SqlCommand = New SqlCommand
Dim msgText = tb_text.Text
Dim reciever As IMSUser = lb_Online.SelectedItem
Dim insert_string As String = "Insert INTO dbo.IMSMessages(Text,RecieverHost,SenderHost,isRead,isRecieved,Stamp) Values(#Text,#RecieverHost,#SenderHost,#isRead,#isRecieved,#Stamp)"
Dim adapter As SqlDataAdapter = New SqlDataAdapter
Dim table As DataTable = New DataTable()
Try
If Not sqlConn.State = ConnectionState.Open Then
sqlConn.Open()
End If
command.Connection = sqlConn
command.CommandText = insert_string
adapter.SelectCommand = command
adapter.Fill(table)
command.CommandText = insert_string
command.Parameters.Add("#Text", SqlDbType.VarChar).Value = msgText
command.Parameters.Add("#RecieverHost", SqlDbType.NChar).Value = reciever.HostName
command.Parameters.Add("#SenderHost", SqlDbType.NChar).Value = user.HostName
command.Parameters.Add("#isRecieved", SqlDbType.Bit).Value = 0
command.Parameters.Add("#isRead", SqlDbType.Bit).Value = 0
command.Parameters.Add("#Stamp", SqlDbType.SmallDateTime).Value = DateTime.Now
command.ExecuteNonQuery()
Catch ex As Exception
Console.WriteLine("onSend: internal database exception" + ex.Message)
End Try
End Sub
Private Sub processMessageId(refMessageID As Integer)
Dim command As SqlCommand = New SqlCommand
Dim msgID_string As String = "SELECT * from dbo.IMSMessages " &
"WHERE MessageID=#MessageID AND isRecieved = 0" &
" ORDER BY Stamp"
Dim isRecievedUpdate_string As String = "Update dbo.IMSMessages " &
"SET isRecieved=1" &
" WHERE MessageID=#MessageID"
Dim adapter As SqlDataAdapter = New SqlDataAdapter
Dim table As DataTable = New DataTable()
Try
If Not sqlConn.State = ConnectionState.Open Then
sqlConn.Open()
End If
command = New SqlCommand
command.CommandText = msgID_string
command.Parameters.Add("#MessageID", SqlDbType.Int).Value = refMessageID
command.Connection = sqlConn
adapter.SelectCommand = command
adapter.Fill(table)
command = New SqlCommand
command.Connection = sqlConn
command.CommandText = isRecievedUpdate_string
command.Parameters.Add("#MessageID", SqlDbType.Int).Value = refMessageID
command.ExecuteNonQuery()
Catch ex As Exception
Console.WriteLine("processMessageID: internal database exception" + ex.Message)
End Try
Try
Dim row As DataRow = table.Rows(0)
Dim senderHost As String = row("SenderHost")
Dim sender As IMSUser = New IMSUser(senderHost)
Dim currentSheet As IMSSheet
Dim stringText As String = row("Text")
Dim stamp As Date = row("Stamp")
currentSheet = New IMSSheet(sender, stringText, stamp)
currentSheet.Show()
Catch ex As Exception
Console.WriteLine("processMessageID: error while showing sheet")
End Try
End Sub
Public Sub recieveNewMessages(newMessageTable As DataTable)
For Each row As DataRow In newMessageTable.Rows
Dim id As Integer = row("MessageID")
processMessageId(id)
Next
End Sub
Public Sub updateOnlineUserList()
lb_Online.Items.Clear()
Dim adapter As SqlDataAdapter = New SqlDataAdapter
Dim table As DataTable = New DataTable()
Dim command As SqlCommand = New SqlCommand
Dim onlineUser_string = "Select * FROM dbo.IMSUser"
command.CommandText = onlineUser_string
Try
If Not sqlConn.State = ConnectionState.Open Then
sqlConn.Open()
End If
command.Connection = sqlConn
adapter.SelectCommand = command
adapter.Fill(table)
Catch ex As Exception
Console.WriteLine("internal database exception" + ex.Message)
End Try
For Each row As DataRow In table.Rows
Dim tmp As IMSUser = New IMSUser(row("HostName"))
If Not user.Equals(tmp) Then
lb_Online.Items.Add(tmp)
End If
Next
End Sub
End Class
IMSSheet-Form:
Public Class IMSSheet
Dim IsDraggingForm As Boolean = False
Private MousePos As New System.Drawing.Point(0, 0)
Public Sub New(session As IMSUser, text As String, stamp As Date)
Ini
tializeComponent()
Me.tb_sender.Text = session.HostName
addText(text, stamp)
End Sub
Private Sub addText(msg As String, stamp As DateTime)
Dim currentText As String = tb_text.Text
currentText = currentText + stamp.ToString + Environment.NewLine + msg + Environment.NewLine
tb_text.Text = currentText
End Sub
Private Sub IMSSheet_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles MyBase.MouseDown
If e.Button = MouseButtons.Left Then
IsDraggingForm = True
MousePos = e.Location
End If
End Sub
Private Sub IMSSheet_MouseUp(ByVal sender As Object, ByVal e As MouseEventArgs) Handles MyBase.MouseUp
If e.Button = MouseButtons.Left Then IsDraggingForm = False
End Sub
Private Sub IMSSheet_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs) Handles MyBase.MouseMove
If IsDraggingForm Then
Dim temp As Point = New Point(Me.Location + (e.Location - MousePos))
Me.Location = temp
temp = Nothing
End If
End Sub
Private Sub onClose(sender As Object, e As EventArgs) Handles bt_Close.Click
Me.Close()
End Sub
Private Sub bt_minimize_Click(sender As Object, e As EventArgs) Handles bt_minimize.Click
Me.WindowState = FormWindowState.Minimized
End Sub
Private Sub bt_Close_MouseHover(sender As Object, e As EventArgs) Handles bt_Close.MouseHover
End Sub
Private Sub bt_minimize_MouseHover(sender As Object, e As EventArgs) Handles bt_minimize.MouseHover
End Sub
End Class
Interesting is that if I have already some new Messages in my Messagestable before I run the programm they are going to be displayed correctly.
If I display the sheets using Form.ShowDialog() it works as well but its not how I want it to work.
As I am out of ideas I hope you can help me.
You are running into issues because the change event of SqlDependency occurs on a different thread that your UI thread. From the SqlDepending documentation:
The OnChange event may be generated on a different thread from the
thread that initiated command execution.
When calling sheet.Show() on a non UI thread, Show() will lockup because there is no message loop to handle the UI events. Use Invoke() on ImsMain to create and show the ImsSheet on your UI thread.