I insert unique data into SQL Server, but it is inserted twice. It happens one or twice time a year. When I delete inserted data and run procedure again, it doesn't happen on same data again. What is the reason and how to avoid it?
I use a SQL Server stored procedure, where is many select, use sequence, insert is in cursor. In procedure there is begin and commit transaction around insert. Duplicate happens for more orders, but after insert data for one order, there is commit. Error happens in one minute and another batch of inserts few minutes later, is OK.
using System;
using System.Diagnostics;
using System.ServiceProcess;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
//using System.
using System.Text;
using System.Timers;
using System.IO;
using System.Configuration;
namespace WindowsService
{
class WindowsService : ServiceBase
{
Timer myTimer;
bool _smyckaBezi;
public WindowsService()
{
this.ServiceName = "Windows Service Jobs OSTRA SAP";
this.EventLog.Log = "Application";
// These Flags set whether or not to handle that specific
// type of event. Set to true if you need it, false otherwise.
this.CanHandlePowerEvent = true;
this.CanHandleSessionChangeEvent = true;
this.CanPauseAndContinue = true;
this.CanShutdown = true;
this.CanStop = true;
}
static void Main()
{
ServiceBase.Run(new WindowsService());
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
}
protected override void OnStart(string[] args)
{
base.OnStart(args);
myTimer = new Timer(5000); // Sets a 10 second interval
myTimer.Elapsed += new ElapsedEventHandler(myTimer_Elapsed);// Specifies The Event Handler
myTimer.Enabled = true; // Enables the control
myTimer.AutoReset = true; // makes it repeat
myTimer.Start();
}
protected void myTimer_Elapsed(object sender, ElapsedEventArgs e)
{
if (_smyckaBezi) return;
_smyckaBezi = true;
SqlConnection conn = null;
string output = null;
List<string> list = new List<string>();
try
{
Config config = new Config();
string cs = ConfigurationManager.ConnectionStrings["connectionStringName"].ConnectionString;
conn = new SqlConnection(cs);
conn.Open();
SqlCommand command = conn.CreateCommand();
command.CommandText = "SELECT TOP 1 procedure_name AS [procedure_name] FROM dbo.jobs_sap WHERE datediff(minute, next_execution, getdate())>=0 AND upper(procedure_name) IN (SELECT upper(s.name)+'.'+upper(o.name) FROM sys.objects o JOIN sys.schemas s ON o.schema_id=s.schema_id WHERE o.type='P') ORDER BY next_execution";
command.CommandType = CommandType.Text;
// execute the command that returns a SqlDataReader
SqlDataReader reader = command.ExecuteReader();
// display the results
while (reader.Read())
{
output = reader["procedure_name"].ToString();
list.Add(output);
}
reader.Close();
for (int i = 0; i < list.Count; i++) // Loop through List with for
{
string pname = list[i];
string sql = "UPDATE dbo.jobs_sap SET last_execution = next_execution WHERE execution_time is not null AND procedure_name= '" + pname + "';";
SqlCommand cmdu = new SqlCommand(sql, conn);
cmdu.ExecuteNonQuery();
sql = "UPDATE dbo.jobs_sap SET next_execution = convert(datetime,CAST(getdate()+1 AS DATE)) + CAST(execution_time AS DATETIME) WHERE execution_time is not null AND procedure_name= '" + pname + "';";
cmdu = new SqlCommand(sql, conn);
cmdu.ExecuteNonQuery();
string sql2 = "UPDATE dbo.jobs_sap SET last_execution = next_execution WHERE execute_every_min is not null AND procedure_name= '" + pname + "';";
SqlCommand cmdu2 = new SqlCommand(sql2, conn);
cmdu2.ExecuteNonQuery();
sql2 = "UPDATE dbo.jobs_sap SET next_execution = dateadd(minute, execute_every_min,getdate()) WHERE execute_every_min is not null AND procedure_name= '" + pname + "';";
cmdu2 = new SqlCommand(sql2, conn);
cmdu2.ExecuteNonQuery();
_smyckaBezi = false;
SqlCommand cmd = new SqlCommand(list[i], conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandTimeout = 0;
cmd.ExecuteNonQuery();
}
}
catch(Exception ex)// catch (InvalidCastException e)
{
writeToLogFileService(ex.ToString());
}
finally
{
if (conn != null)
{
conn.Close();
_smyckaBezi = false;
}
}
}
public static void writeToLogFileService(string logMessage)
{
string str_LogMessage = string.Empty;
string str_LogFile = "d:\\temp\\log_jobs_sap.txt";
StreamWriter swLog;
str_LogMessage = string.Format("{0}: {1}", DateTime.Now, logMessage);
if (!File.Exists(str_LogFile))
{
swLog = new StreamWriter(str_LogFile);
}
else
{
swLog = File.AppendText(str_LogFile);
}
swLog.WriteLine(str_LogMessage);
swLog.WriteLine();
swLog.Close();
}
protected override void OnStop()
{
base.OnStop();
}
protected override void OnPause()
{
base.OnPause();
}
protected override void OnContinue()
{
base.OnContinue();
}
protected override void OnShutdown()
{
base.OnShutdown();
}
protected override void OnCustomCommand(int command)
{
base.OnCustomCommand(command);
}
protected override bool OnPowerEvent(PowerBroadcastStatus powerStatus)
{
return base.OnPowerEvent(powerStatus);
}
protected override void OnSessionChange(
SessionChangeDescription changeDescription)
{
base.OnSessionChange(changeDescription);
}
}
}
using System;
using System.ComponentModel;
using System.Configuration.Install;
using System.ServiceProcess;
namespace WindowsService
{
[RunInstaller(true)]
public class WindowsServiceInstaller : Installer
{
/// <summary>
/// Public Constructor for WindowsServiceInstaller.
/// - Put all of your Initialization code here.
/// </summary>
public WindowsServiceInstaller()
{
ServiceProcessInstaller serviceProcessInstaller =
new ServiceProcessInstaller();
ServiceInstaller serviceInstaller = new ServiceInstaller();
//# Service Account Information
serviceProcessInstaller.Account = ServiceAccount.LocalSystem;
serviceProcessInstaller.Username = null;
serviceProcessInstaller.Password = null;
//# Service Information
serviceInstaller.DisplayName = "Windows Service Jobs OSTRA SAP";
serviceInstaller.StartType = ServiceStartMode.Automatic;
//# This must be identical to the WindowsService.ServiceBase name
//# set in the constructor of WindowsService.cs
serviceInstaller.ServiceName = "Windows Service Jobs OSTRA SAP";
this.Installers.Add(serviceProcessInstaller);
this.Installers.Add(serviceInstaller);
}
}
}
Thanks for comments, it was helpfull. C# service fired procedure twice times. So I added second control directly into service (first check in procedure was not enough). Solution:
using System;
using System.Diagnostics;
using System.ServiceProcess;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
//using System.
using System.Text;
using System.Timers;
using System.IO;
using System.Configuration;
using log4net;
namespace WindowsService
{
class WindowsService : ServiceBase
{
Timer myTimer;
bool _smyckaBezi;
private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public WindowsService()
{
this.ServiceName = "Windows Service Jobs";
this.EventLog.Log = "Application";
// These Flags set whether or not to handle that specific
// type of event. Set to true if you need it, false otherwise.
this.CanHandlePowerEvent = true;
this.CanHandleSessionChangeEvent = true;
this.CanPauseAndContinue = true;
this.CanShutdown = true;
this.CanStop = true;
}
static void Main(string[] args)
{
log4net.Config.XmlConfigurator.Configure();
if (args.Length > 0 && args[0] == "/console")
{
WindowsService ws = new WindowsService();
ws.Start();
System.Threading.Thread.Sleep(int.MaxValue);
}
else
{
ServiceBase.Run(new WindowsService());
}
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
}
protected override void OnStart(string[] args)
{
base.OnStart(args);
myTimer = new Timer(10000); // Sets a 10 second interval
myTimer.Elapsed += new ElapsedEventHandler(myTimer_Elapsed);// Specifies The Event Handler
myTimer.Enabled = true; // Enables the control
myTimer.AutoReset = true; // makes it repeat
myTimer.Start();
}
public void Start()
{
//base.OnStart(args);
myTimer = new Timer(10000); // Sets a 10 second interval
myTimer.Elapsed += new ElapsedEventHandler(myTimer_Elapsed);// Specifies The Event Handler
myTimer.Enabled = true; // Enables the control
myTimer.AutoReset = true; // makes it repeat
myTimer.Start();
}
protected void myTimer_Elapsed(object sender, ElapsedEventArgs e)
{
using (LogEx le = new LogEx(log))
{
if (_smyckaBezi) return;
_smyckaBezi = true;
SqlConnection conn = null;
string output = null;
List<string> list = new List<string>();
try
{
Config config = new Config();
string cs = ConfigurationManager.ConnectionStrings["connectionStringName"].ConnectionString;
conn = new SqlConnection(cs);
conn.Open();
SqlCommand command = conn.CreateCommand();
command.CommandText = "SELECT TOP 1 procedure_name AS [procedure_name] FROM dbo.jobs_crm WHERE ISNULL(spusteno_WS,0)=0 AND datediff(minute, next_execution, getdate())>=0 AND upper(procedure_name) IN (SELECT upper(s.name)+'.'+upper(o.name) FROM sys.objects o JOIN sys.schemas s ON o.schema_id=s.schema_id WHERE o.type='P') ORDER BY next_execution";
command.CommandType = CommandType.Text;
// execute the command that returns a SqlDataReader
SqlDataReader reader = command.ExecuteReader();
// display the results
while (reader.Read())
{
output = reader["procedure_name"].ToString();
list.Add(output);
}
reader.Close();
for (int i = 0; i < list.Count; i++) // Loop through List with for
{
string pname = list[i];
try
{
string sql = "UPDATE dbo.jobs_crm SET spusteno_WS=1, last_execution = getdate(), next_execution = convert(datetime,CAST(getdate()+1 AS DATE)) + CAST(execution_time AS DATETIME) WHERE execution_time is not null AND procedure_name= '" + pname + "';";
SqlCommand cmdu = new SqlCommand(sql, conn);
cmdu.ExecuteNonQuery();
string sql2 = "UPDATE dbo.jobs_crm SET spusteno_WS=1, last_execution = getdate(), next_execution = dateadd(minute, execute_every_min,getdate()) WHERE execute_every_min is not null AND procedure_name= '" + pname + "';";
SqlCommand cmdu2 = new SqlCommand(sql2, conn);
cmdu2.ExecuteNonQuery();
_smyckaBezi = false;
//execute procedure
SqlCommand cmd = new SqlCommand(list[i], conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandTimeout = 0;
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
Console.WriteLine(pname + " > " + ex.Message + (ex.InnerException != null ? ex.InnerException.Message : ""));
//le.Exception(ex);
le.Error(pname + " > " + ex.Message + (ex.InnerException != null ? ex.InnerException.Message : ""));
}
finally
{
string sql3 = "UPDATE dbo.jobs_crm SET spusteno_WS=0 WHERE procedure_name= '" + pname + "';";
SqlCommand cmdu3 = new SqlCommand(sql3, conn);
cmdu3.ExecuteNonQuery();
}
}
}
catch (Exception ex)// catch (InvalidCastException e)
{
Console.WriteLine(ex.Message + (ex.InnerException != null ? ex.InnerException.Message : ""));
le.Error("Obecná chyba > " + ex.Message + (ex.InnerException != null ? ex.InnerException.Message : ""));
//writeToLogFileService(ex.ToString());
}
finally
{
if (conn != null)
{
conn.Close();
_smyckaBezi = false;
} } } }
public static void writeToLogFileService(string logMessage)
{
string str_LogMessage = string.Empty;
string str_LogFile = "d:\\temp\\log_jobs_test_crm.txt";
StreamWriter swLog;
str_LogMessage = string.Format("{0}: {1}", DateTime.Now, logMessage);
if (!File.Exists(str_LogFile))
{
swLog = new StreamWriter(str_LogFile);
}
else
{
swLog = File.AppendText(str_LogFile);
}
swLog.WriteLine(str_LogMessage);
swLog.WriteLine();
swLog.Close();
}
protected override void OnStop()
{
base.OnStop();
}
protected override void OnPause()
{
base.OnPause();
}
protected override void OnContinue()
{
base.OnContinue();
}
protected override void OnShutdown()
{
base.OnShutdown();
}
protected override void OnCustomCommand(int command)
{
base.OnCustomCommand(command);
}
protected override bool OnPowerEvent(PowerBroadcastStatus powerStatus)
{
return base.OnPowerEvent(powerStatus);
}
protected override void OnSessionChange(
SessionChangeDescription changeDescription)
{
base.OnSessionChange(changeDescription);
}
}
}
Related
I looked for a solution to this problem on the forum, but I didn't find one for my problem. On button click, I receive error:
There is already an open DataReader associated with this Connection which must be closed first.
So, I tried to close all DataReaders after using them, I tried to use CommandBehavior, but none of them worked. I tried to use using(MysqlCommand...) but didn't work. What can I do? The strangest thing is that the code is working, but after each button press, I receive that error again. Any ideas?
Please don't flag question as a duplicate, I know that the question exist here but the answer is missing for my problem I guess.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using MySql.Data.MySqlClient;
using System.Drawing.Text;
namespace simulator
{
public partial class Simulare : Form
{
public int corect = 0, incorect = 0;
Timer timer;
static string dataA = "SELECT DISTINCT * FROM questions order by rand() limit 1";
public int r1;
public int r2;
public int r3;
public Simulare()
{
InitializeComponent();
this.FormClosing += Form1_FormClosing;
label1.Text = TimeSpan.FromMinutes(30).ToString("mm\\:ss");
label10.Text = corect.ToString();
label12.Text = incorect.ToString();
//FormBorderStyle = FormBorderStyle.None;
WindowState = FormWindowState.Maximized;
}
private void simulare_Load(object sender, EventArgs e)
{
var startTime = DateTime.Now;
timer = new Timer() { Interval = 1000 };
timer.Tick += (obj, args) =>
{
TimeSpan ts = TimeSpan.FromMinutes(30) - (DateTime.Now - startTime);
label1.Text = ts.ToString("mm\\:ss");
if (ts.Minutes == 00 && ts.Seconds == 00)
{
timer.Stop();
MessageBox.Show("Timpul a expirat. Ai picat!");
MySqlCommand upd = new MySqlCommand("select totalno from accounts where username = '" + Index.textBox1.Text + "'", ConnConfig.getConnection());
try
{
MySqlDataReader upad = upd.ExecuteReader();
while (upad.Read())
{
int totalnu = (int)upad["totalno"];
totalnu++;
using (MySqlCommand update = new MySqlCommand("UPDATE accounts SET totalno=#totalnu where username = '" + Index.textBox1.Text + "'", ConnConfig.getConnection()))
{
update.Parameters.AddWithValue("#totalnu", totalnu);
int rows = update.ExecuteNonQuery();
}
}
upad.Close();
}
catch (Exception ex2)
{
MessageBox.Show(ex2.Message);
}
}
};
timer.Start();
select();
}
private void select()
{
using (ConnConfig.getConnection())
{
MySqlCommand cmd = new MySqlCommand(dataA, ConnConfig.getConnection());
cmd.CommandType = CommandType.Text;
MySqlDataReader rdra = cmd.ExecuteReader(CommandBehavior.CloseConnection);
try
{
while (rdra.Read())
{
label2.Text = rdra["question"].ToString();
label3.Text = rdra["answer1"].ToString();
label4.Text = rdra["answer2"].ToString();
label5.Text = rdra["answer3"].ToString();
r1 = (int)rdra["option1"];
r2 = (int)rdra["option2"];
r3 = (int)rdra["option3"];
}
rdra.Close();
}
catch (InvalidOperationException ex)
{
MessageBox.Show(ex.Message);
}
finally
{
ConnConfig.closeConn();
}
}
}
private void button1_Click(object sender, EventArgs e)
{
int result1 = checkBox1.CheckState == CheckState.Checked ? 1 : 0;
int result2 = checkBox2.CheckState == CheckState.Checked ? 1 : 0;
int result3 = checkBox3.CheckState == CheckState.Checked ? 1 : 0;
using(ConnConfig.getConnection())
{
MySqlCommand cmd = new MySqlCommand(dataA, ConnConfig.getConnection());
cmd.CommandType = CommandType.Text;
MySqlDataReader rdr = cmd.ExecuteReader();
try
{
while (rdr.Read())
{
if (checkBox1.Checked == false && checkBox2.Checked == false && checkBox3.Checked == false)
{
MessageBox.Show("Bifati minim o casuta!");
return;
}
else
{
if ((result1 == r1) && (result2 == r2) && (result3 == r3))
{
corect++;
label10.Text = corect.ToString();
checkBox1.Checked = false;
checkBox2.Checked = false;
checkBox3.Checked = false;
select();
}
else
{
incorect++;
label12.Text = incorect.ToString();
checkBox1.Checked = false;
checkBox2.Checked = false;
checkBox3.Checked = false;
select();
}
if (corect + incorect == 26)
{
int totalalll;
timer.Stop();
button1.Enabled = false;
MySqlCommand upd = new MySqlCommand("select * from accounts where username = '" + Index.textBox1.Text + "'", ConnConfig.getConnection());
MySqlDataReader upad = upd.ExecuteReader();
while (upad.Read())
{
totalalll = (int)upad["totalall"];
totalalll++;
using (MySqlCommand update = new MySqlCommand("UPDATE accounts SET totalall=#totalalll where username = '" + Index.textBox1.Text + "'", ConnConfig.getConnection()))
{
update.Parameters.AddWithValue("#totalalll", totalalll);
Int32 rows = update.ExecuteNonQuery();
}
}
upad.Close();
}
if (corect == 26)
{
MySqlCommand upd = new MySqlCommand("select totalyes from accounts where username = '" + Index.textBox1.Text + "'", ConnConfig.getConnection());
MySqlDataReader upad = upd.ExecuteReader();
while (upad.Read())
{
int totalda = (Int32)upad["totalyes"];
totalda++;
using (MySqlCommand update = new MySqlCommand("UPDATE accounts SET totalyes=#totalda where username = '" + Index.textBox1.Text + "'", ConnConfig.getConnection()))
{
update.Parameters.AddWithValue("#totalda", totalda);
int rows = update.ExecuteNonQuery();
}
}
upad.Close();
MessageBox.Show("Bravos");
}
else
{
MySqlCommand upd = new MySqlCommand("select totalno from accounts where username = '" + Index.textBox1.Text + "'", ConnConfig.getConnection());
MySqlDataReader upad = upd.ExecuteReader();
while (upad.Read())
{
int totalnu = (int)upad["totalno"];
totalnu++;
using (MySqlCommand update = new MySqlCommand("UPDATE accounts SET totalno=#totalnu where username = '" + Index.textBox1.Text + "'", ConnConfig.getConnection()))
{
update.Parameters.AddWithValue("#totalnu", totalnu);
int rows = update.ExecuteNonQuery();
}
}
upad.Close();
MessageBox.Show("Mai invata!");
}
}
}
rdr.Close();
}
catch (MySqlException ex)
{
MessageBox.Show(ex.Message);
}
finally
{
ConnConfig.closeConn();
}
}
}
private void Form1_FormClosing(Object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.WindowsShutDown) return;
if (this.DialogResult == DialogResult.Cancel)
{
e.Cancel = false;
timer.Stop();
}
}
private void button2_Click(object sender, EventArgs e)
{
this.Close();
}
}
}
class ConnConfig
{
private static string conn = "string connection";
public static MySqlConnection connect;
private ConnConfig()
{
}
public static MySqlConnection getConnection()
{
if(connect !=null){
return connect;
}
else
try{
connect = new MySqlConnection(conn);
connect.Open();
return connect;
}
catch(MySqlException e){
throw new Exception("Cannot connect",e);
}
}
public static void closeConn()
{
connect.Close();
}
public static void openConn()
{
connect.Open();
}
}
Change the getConnection function
public static MySqlConnection getConnection()
{
MySqlConnection connect = null;
try
{
connect = new MySqlConnection(connect);
connect.Open();
return connect;
}
catch (MySqlException e)
{
throw new Exception("Cannot connect", e);
}
}
let all the other codes as it is
The root cause of your exception is that you are executing other queries while you are still iterating over the results of an earlier query.
Bottom line you should not nest queries like you do if you use the same connection for the nested queries.
You are using reader to fetch data from SQLCommand upd.
Then you are reading value.
After that you are using another SqlCommand 'update' to update the result..
Even when you use two different SQLCommands, you are using the same connection. Thats the problem. Use a sperate connection for the second SQLCommand and your problem will be solved.
Try this.
after the line
MessageBox.Show("Timpul a expirat. Ai picat!");
add like
MessageBox.Show("Timpul a expirat. Ai picat!");
MySqlConnection conn1 = ConnConfig.getConnection();
MySqlConnection conn2 = new MySqlConnection();
conn2.ConnectionString = conn1.ConnectionString;
conn2.Open();
and then in the line
MySqlCommand upd = new MySqlCommand("select totalno from accounts where username = '" + Index.textBox1.Text + "'", ConnConfig.getConnection());
change like
MySqlCommand upd = new MySqlCommand("select totalno from accounts where username = '" + Index.textBox1.Text + "'", conn1);
and in line
using (MySqlCommand update = new MySqlCommand("UPDATE accounts SET totalno=#totalnu where username = '" + Index.textBox1.Text + "'", ConnConfig.getConnection()))
change like
using (MySqlCommand update = new MySqlCommand("UPDATE accounts SET totalno=#totalnu where username = '" + Index.textBox1.Text + "'", conn2))
I have written this class to automate SQLDependencys
public class DatabaseChangeAlert
{
private String connectionString;
private SqlConnection sc;
public event EventHandler<DatabaseChangedEvent> DatabaseChangeEvent;
private String tabelle;
private String query;
public DatabaseChangeAlert(String tabelle, String conString)
{
try
{
this.tabelle = tabelle;
this.sc = new SqlConnection(conString); ;//new SqlConnection(GlobalResources.ConnectionString);
this.connectionString = conString;
String sel = "";
using (SqlConnection con = new SqlConnection(conString))
{
con.Open();
SqlCommand cmd = con.CreateCommand();
cmd.CommandText = "SELECT dbo.syscolumns.name AS Spaltenname " +
" FROM dbo.syscolumns INNER JOIN " +
" dbo.sysobjects ON dbo.syscolumns.id = dbo.sysobjects.id " +
" WHERE (dbo.sysobjects.xtype = 'U') and dbo.sysobjects.name='" + tabelle + "' ";
using (SqlDataReader sr = cmd.ExecuteReader())
{
while (sr.Read())
{
sel += "["+sr.GetString(0)+"],";
}
}
sel = sel.Substring(0, sel.Length - 1);
}
query = "SELECT " + sel + " from [dbo].[" + tabelle+"]";
}
catch (Exception ex) { }
}
~DatabaseChangeAlert()
{
if(connectionString!=null)
SqlDependency.Stop(connectionString);
}
public void start()
{
try
{
SqlDependency.Start(connectionString);
}
catch (Exception ex)
{
// log(ex)
}
try
{
startDependency();
}
catch (Exception ex)
{
// log(ex)
}
}
private void startDependency()
{
// Assume connection is an open SqlConnection.
// Create a new SqlCommand object.
using (SqlCommand command = new SqlCommand(query, sc))
{
sc.Open();
// Create a dependency and associate it with the SqlCommand.
SqlDependency dependency = new SqlDependency(command);
// Maintain the refence in a class member.
// Subscribe to the SqlDependency event.
dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
// Execute the command.
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
}
}
sc.Close();
}
}
void dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
if (e.Info != SqlNotificationInfo.Invalid)
{
startDependency();
if (DatabaseChangeEvent != null)
{
DatabaseChangeEvent(this, new DatabaseChangedEvent(tabelle,e.Info));
}
}
}
public class DatabaseChangedEvent : EventArgs
{
public readonly String Tablename;
public readonly SqlNotificationInfo info;
public DatabaseChangedEvent(String tablename,SqlNotificationInfo info)
{
this.Tablename = tablename;
this.info = info;
}
}
}
in my program I use this Class like that:
DatabaseChangeAlert alerttz = new DatabaseChangeAlert("table1", GlobalResources.ConnectionString);
alerttz.DatabaseChangeEvent += (e,d)=>{
MessageBox.Show("table1 changed");
};
alerttz.start();
DatabaseChangeAlert alert = new DatabaseChangeAlert("table2", GlobalResources.ConnectionString);
alert.DatabaseChangeEvent += (e, d) =>
{
MessageBox.Show("table2 changed");
};
alert.start();
Now my Problem is that when I change anything in table2 I do not get a notification, but when I do the same for table 1 I get a notification!
any ideas what the problem could be?
I also tried to only suscribe for table2...but it remain the same.
I've repeated your situation and wrote unit test (TwoTablesNotificationTest), but didn't find anything. It works fine for me. In this situation you could stop receive notifications from SqlDependency in case of destructor call of some DatabaseChangeAlert entity, because it has SqlDependency.Stop(connectionString) instruction. Thus, you have to call SqlDependency.Start after every SqlDependency.Stop to continue receiving events, but destructor is called automatically by garbage collector from parallel thread and it may cause this effect.
And I want to warn you - be careful using SqlDependency class because it has memory leak problem. For my project I used open source realization of SqlDependency - SqlDependencyEx. It is very easy to use:
int changesReceived = 0;
using (SqlDependencyEx sqlDependency = new SqlDependencyEx(
TEST_CONNECTION_STRING, TEST_DATABASE_NAME, TEST_TABLE_NAME))
{
sqlDependency.TableChanged += (o, e) => changesReceived++;
sqlDependency.Start();
// Make table changes.
MakeTableInsertDeleteChanges(changesCount);
// Wait a little bit to receive all changes.
Thread.Sleep(1000);
}
Assert.AreEqual(changesCount, changesReceived);
Hope this helps.
How to show progressbar while sending email using backgroundworker in C#. It should show step by step as we can see while we copy anything to our drive.I am reading excel file to send email.
progressbar1.performstep();
OnClick of Button i am showing Progressbar
private void button2_Click(object sender, EventArgs e)
{
progressBar1.Visible = true;
percentageLabel.Visible = true;
backgroundWorker1.RunWorkerAsync();
}
On progress changed event : what to do ??
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progresBar1.PerformStep();
}
On Do work sendmail : (Note : I need backgroundWorker1.ReportProgress should perform step by step, problem is here i knoww but how to do and what to ? please help here)
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
backgroundWorker1.ReportProgress(98);
while (!quit)
{
// Code to send email here
sendmail();
}
}
void sendmail()
{
string ConStr = "";
ConStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\Program Files\\CreditControl\\CC\\outstanding.xlsx;Extended Properties=\"Excel 8.0;HDR=YES;IMEX=1;\"";
string query = "SELECT [Agent ID] FROM [Sheet1$] group by [Agent ID] ";
OleDbConnection conn = new OleDbConnection(ConStr);
OleDbCommand cmd = new OleDbCommand(query, conn);
OleDbDataAdapter da = new OleDbDataAdapter(cmd);
System.Data.DataTable dt = new System.Data.DataTable();
da.Fill(dt);
conn.Close();
for (int i = 0; i < dt.Rows.Count; i++)
{
if (dt.Rows[i]["Agent ID"].ToString() != "")
{
ConStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\Program Files\\CreditControl\\CC\\agent_mail_master.xlsx;Extended Properties=\"Excel 8.0;HDR=YES;IMEX=1;\"";
string query2 = "SELECT Mail1,Mail2,Mail3,Mail4,Mail5 FROM [Sheet1$] where [Agent ID] = '" + dt.Rows[i]["Agent ID"].ToString() + "'";
OleDbConnection conn2 = new OleDbConnection(ConStr);
if (conn2.State == ConnectionState.Closed)
{
conn2.Open();
}
OleDbCommand cmd1 = new OleDbCommand(query2, conn2);
OleDbDataAdapter sda = new OleDbDataAdapter(cmd1);
System.Data.DataTable dts = new System.Data.DataTable();
sda.Fill(dts);
conn2.Close();
if (dts.Rows.Count > 0)
{
try
{
SmtpClient SmtpServer = new SmtpClient();
MailMessage mail = new MailMessage();
SmtpServer.Credentials = new System.Net.NetworkCredential("");
SmtpServer.Port = 25;
SmtpServer.Host = "";
mail.From = new MailAddress("");
if (dts.Rows[0]["Mail1"].ToString() != "")
mail.To.Add(dts.Rows[0]["Mail1"].ToString());
if (dts.Rows[0]["Mail2"].ToString() != "")
mail.To.Add(dts.Rows[0]["Mail2"].ToString());
if (dts.Rows[0]["Mail3"].ToString() != "")
mail.To.Add(dts.Rows[0]["Mail3"].ToString());
if (dts.Rows[0]["Mail4"].ToString() != "")
mail.To.Add(dts.Rows[0]["Mail4"].ToString());
if (dts.Rows[0]["Mail5"].ToString() != "")
mail.To.Add(dts.Rows[0]["Mail5"].ToString());
mail.Subject = "";
mail.IsBodyHtml = true;
ConStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\Program Files\\CreditControl\\CC\\outstanding.xlsx;Extended Properties=\"Excel 8.0;HDR=YES;IMEX=1;\"";
string query3 = "Select [Date],[Agency Name] ,[Agent ID],[Delay Days],[OD Amount],[Receipt Amount],[Outstanding Amount],Remarks,[Entered By] FROM [Sheet1$] where [Agent ID] ='" + dt.Rows[i]["Agent ID"].ToString() + "'";
OleDbConnection conn3 = new OleDbConnection(ConStr);
OleDbCommand cmd2 = new OleDbCommand(query3, conn3);
OleDbDataAdapter oda = new OleDbDataAdapter(cmd2);
System.Data.DataTable dta = new System.Data.DataTable();
oda.Fill(dta);
conn3.Close();
StringBuilder sb = new StringBuilder();
mail.Body = sb.ToString();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
quit = true;
}
ON backgroundWorker_RunWorkerCompleted success message :
private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
progressBar1.Visible = false;
percentageLabel.Text = "";
MessageBox.Show("Error");
return;
}
else
{
MessageBox.Show("Processed successfully");
System.Windows.Forms.Application.Exit();
}
}
you need to fire the ProgressChangedEvent. something like
bgWorker.ReportProgress( PercentageCompleted(...) );
also be advised that progressBar1.Value expects an Int32 between 0 .. 100 and not a Double between 0 .. 1 (from your code it is not obvious what value you are reporting to your BackgroundWorker)
for ReportStep be sure you set all the required properties. you can find an example on MSDN here
http://msdn.microsoft.com/en-us/library/system.windows.forms.progressbar.performstep(v=vs.110).aspx
so in that case you would need to call pbar1.ReportStep() in your ProressChanged-Method instead of setting the Value of pbar1 directly.
EDIT: this is a very basic example from a derived BackgroundWorker how to deal with these events
public sealed class MyBackgroundWorker : BackgroundWorker
{
public MyBackgroundWorker(ProgressBar pBar)
{
this.MyProgressBar = pBar;
this.WorkerReportsProgress = true;
this.WorkerSupportsCancellation = false;
this.DoWork += MyBackgroundWorker_DoWork;
this.ProgressChanged += MyBackgroundWorker_ProgressChanged;
this.RunWorkerCompleted += MyBackgroundWorker_RunWorkerCompleted;
}
public ProgressBar MyProgressBar { get; private set; }
void MyBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("Finish");
}
void MyBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
SendMail();
}
void MyBackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
Boolean either = true; // These are your choices
if (either)
{
// If the ProgressBar has been properly configured regarding
//
// this.myProgressBar.Minimum
// and
// this.myProgressBar.Maximum
//
// you can simply call
this.MyProgressBar.PerformStep();
}
else
{
// If the Progressbar has not been properly configured,
// you have to assign the value provided by
// ProgressChangedEvents e like this
this.MyProgressBar.Value = e.ProgressPercentage;
}
}
private Boolean SendMail()
{
// foreach mail in MailsToSend ...
// Snip - I assume your code for sending mails works correctly
try
{
// Snip
}
catch (Exception ex)
{
// Snip
}
finally
{
this.ReportProgress( (100 * cntMailsSent) / cntTotalMailsToSend);
}
// quit = true; // What do you use this for?
}
}
i have a problem with my windows service program
i try to create a windows service to read data from a database and insert them into an other database but when i read data from first db and copy it into a dataset i have a problem, i can't read those data from data set and insert it into an other dataset to insert it into the other database
here's my code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Timers;
using System.Data.SqlClient;
using System.Collections;
using System.Data.Sql;
namespace WindowSeriveDemo
{
public partial class Service1 : ServiceBase
{
string connection = #"Data Source=DEVELOPER-PC\DEVELOPER;Initial Catalog=NMSys;User ID=sa;Password=2649940931";
string connection2 = #"Data Source=DEVELOPER-PC\DEVELOPER;Initial Catalog=Dpardazesh;User ID=sa;Password=2649940931";
private Timer ServiceTimer = new Timer();
private int inProcess = 0;
public const string SP_dataRead = "usp_Read_Data_From_DpardazeshDB";
public const string SP_insertData = "usp_Write_Data_Into_NMSysDB";
private IEnumerable<DataRow> item;
//Timer timer1 = new Timer();
public Service1()
{
InitializeComponent();
setupTimer();
}
protected override void OnStart(string[] args)
{
//ServiceTimer.Elapsed += new ElapsedEventHandler(timer1_Elapsed);
}
private void setupTimer()
{
ServiceTimer.Elapsed += new ElapsedEventHandler(ServiceTimer_Tick);
ServiceTimer.Interval = 10000;
ServiceTimer.Enabled = true;
ServiceTimer.Start();
}
protected override void OnStop()
{
//timer1.Enabled = false;
}
private void SyncDatabases()
{
inProcess = 1;
SqlConnection conn2 = new SqlConnection(connection2);
try
{
conn2.Open();
SqlCommand cmd = new SqlCommand(SP_dataRead);
winservDS dataSet = new winservDS();
cmd.CommandType = CommandType.StoredProcedure;
//AddParameter(cmd);
SqlDataAdapter adapter = new SqlDataAdapter(SP_dataRead, conn2);
adapter.Fill(dataSet, dataSet.usp_Read_Data_From_DpardazeshDB.TableName);
dataSet.AcceptChanges();
return ;
}
catch (Exception ex)
{
string text = ex.Message;
}
inProcess = 0;
}
private static SqlCommand cmdGetIdentity;
public winservDS InsertUsers(IDictionary ids)
{
inProcess = 1;
SqlConnection conn = new SqlConnection(connection);
SqlConnection conn2 = new SqlConnection(connection2);
conn.Open();
conn2.Open();
winservDS updates = new winservDS();
DataRow dr;
dr = updates.usp_Read_Data_From_DpardazeshDB.NewRow();
foreach (DictionaryEntry i in ids)
{
if (i.Value == null)
dr[i.Key.ToString()] = DBNull.Value;
else
dr[i.Key.ToString()] = i.Value;
}
updates.usp_Read_Data_From_DpardazeshDB.Rows.Add(dr);
try
{
winservDS.usp_Read_Data_From_DpardazeshDBDataTable tbl = updates.usp_Read_Data_From_DpardazeshDB;
//Create the adapter initial
SqlDataAdapter dataAdapter = new SqlDataAdapter();
dataAdapter.InsertCommand = WriteDatabase(conn);
//Roll Back the changes if some one error have
dataAdapter.ContinueUpdateOnError = false;
cmdGetIdentity = new SqlCommand("SELECT ##IDENTITY", conn);
dataAdapter.RowUpdated += new SqlRowUpdatedEventHandler(HandleRowUpdated);
dataAdapter.Update(tbl.Select("", "", DataViewRowState.Added));
return updates;
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
inProcess = 0;
}
private static void HandleRowUpdated(object sender, SqlRowUpdatedEventArgs e)
{
if ((e.Status == UpdateStatus.Continue) && (e.StatementType == StatementType.Insert))
{
e.Row["id"] = Convert.ToInt32 (cmdGetIdentity.ExecuteScalar());
e.Row.AcceptChanges();
}
}
private static SqlCommand WriteDatabase(SqlConnection conn)
{
SqlCommand cmd = new SqlCommand(SP_insertData);
cmd.Parameters.Clear();
cmd.CommandType = CommandType.StoredProcedure;
SqlParameterCollection pc = cmd.Parameters;
pc.Add(CreateParameter("#fHitType", System.Data.SqlDbType.Int));
pc.Add(CreateParameter("#DateOfHit", System.Data.SqlDbType.DateTime));
pc.Add(CreateParameter("#TimeOfHit", System.Data.SqlDbType.Int));
pc.Add(CreateParameter("#fEmpid", System.Data.SqlDbType.Int));
cmd.ExecuteNonQuery();
return cmd;
}
private static SqlParameter CreateParameter(string p, SqlDbType sqlDbType)
{
SqlParameter parameter = new SqlParameter("#" + p, sqlDbType);
parameter.SourceColumn = p;
return parameter;
}
private void ServiceTimer_Tick(object sender, EventArgs e)
{
if (inProcess == 0)
{
ServiceTimer.Stop();
SyncDatabases();
CopyData();
//InsertUsers(ids);
ServiceTimer.Start();
}
}
private void CopyData()
{
DataSet ds1 = new winservDS();
DataSet ds2 = new In_Out_RecordsDS();
foreach (DataRow item in ds1.Tables[0].Rows)
{
ds2.Tables[0].Rows.Add(item);
}
} here
Try to use a DataReader for the source recordsets, read all columns into variables and then insert them into second database with an INSERT Statement. Be avoid of your transaction log when copying thousands of records...
Why is the where clause being ignored in this code? It seems to be ignoring the where clause on the update which means every records has been written over. How can i fix this? Any help would be greatly appreciated.
namespace ResitAssignment2
{
public partial class HomeCareVisitEddit : Form
{
public HomeCareVisitEddit()
{
InitializeComponent();
}
private void SubmitHCVA_Click(object sender, EventArgs e)
{
SqlConnection a = Database.GetConnection();
a.Open();
string sqltext;
sqltext = #"update HomeCareVisit set
PatientNo=#PatientNo,
FurtherVisitRequired=#FurtherVisitRequired,
AdvisoryNotes=#AdvisoryNotes,
Prescription=#Prescription,
TreatmentProvided=#TreatmentProvided,
ActualVisitDateTime=#ActualVisitDateTime,
Priority=#Priority,
ScheduledDateTime=#ScheduledDateTime,
TreatmentInstructions=#TreatmentInstructions,
MedicalStaffID=#MedicalStaffID
WHERE
VisitRefNo=VisitRefNo";
SqlCommand command = new SqlCommand(sqltext, a);
try
{
using (a)
{
command.Parameters.AddWithValue("#PatientNo", PatientNo.Text);
command.Parameters.AddWithValue("#FurtherVisitRequired", FurtherVisitRequired.Text);
command.Parameters.AddWithValue("#AdvisoryNotes", AdvisoryNotes.Text);
command.Parameters.AddWithValue("#Prescription", Prescription.Text);
command.Parameters.AddWithValue("#TreatmentProvided", TreatmentProvided.Text);
command.Parameters.AddWithValue("#ActualVisitDateTime",SqlDbType.DateTime );
{
DateTime.Parse(ActualVisitDateTime.Text);
};
command.Parameters.AddWithValue("#Priority", Priority.Text);
command.Parameters.AddWithValue("#ScheduledDateTime",SqlDbType.DateTime );
{
DateTime.Parse(ScheduledDateTime.Text);
};
command.Parameters.AddWithValue("#TreatmentInstructions", TreatmentInstructions.Text);
command.Parameters.AddWithValue("#MedicalStaffID", MedicalStaffID.Text);
command.Parameters.AddWithValue("#VisitRefNo", VisitRefNo.Text);
command.ExecuteNonQuery();
MessageBox.Show("Record altered");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
a.Close();
}
private void HomeCareVisitEddit_Load(object sender, EventArgs e)
{
SqlConnection a = Database.GetConnection();
a.Open();
string sqlText = "select * from HomeCareVisit where VisitRefNo =" + VisitRefNo;
SqlCommand command = new SqlCommand(sqlText, a);
SqlDataReader HomeCareVisitData = command.ExecuteReader();
while (HomeCareVisitData.Read())
{
//DateTime actual = DateTime.Parse("ActualVisitDateTime");
//DateTime scheduled = DateTime.Parse("ActualVisitDateTieme");
PatientNo.Text = HomeCareVisitData["PatientNo"].ToString();
FurtherVisitRequired.Text = HomeCareVisitData["FurtherVisitRequired"].ToString();
AdvisoryNotes.Text = HomeCareVisitData["AdvisoryNotes"].ToString();
Prescription.Text = HomeCareVisitData["Prescription"].ToString();
TreatmentProvided.Text = HomeCareVisitData["TreatmentProvided"].ToString();
ActualVisitDateTime.Text = HomeCareVisitData["ActualVisitDateTime"].ToString();
Priority.Text = HomeCareVisitData["Priority"].ToString();
ScheduledDateTime.Text = HomeCareVisitData["ScheduledDateTime"].ToString();
TreatmentInstructions.Text = HomeCareVisitData["TreatmentInstructions"].ToString();
MedicalStaffID.Text = HomeCareVisitData["MedicalStaffID"].ToString();
}
a.Close();
}
}
}
WHERE VisitRefNo=VisitRefNo"; should be WHERE VisitRefNo=#VisitRefNo";.
WHERE VisitRefNo=VisitRefNo
Should be
WHERE VisitRefNo=#VisitRefNo