C# OleDBConnection connecting to previous IP? - c#

I have multiple databases (30+) that are used at clinics and setup automatically via the license software they use. So each database is named the same and use the same port, the only thing that changes is the IP. That being said, I am using the following code to attempt to run a query against them individually. However, when I change out the IP and run the script again it is returning the results from the previous server.
using System;
using System.Diagnostics;
using System.Data.OleDb;
namespace ConnectionTest
{
class Program
{
static void Main(string[] args)
{
using (OleDbConnection conn = new OleDbConnection("Provider=SAOLEDB.10;LINKS=tcpip(host=X.X.X.X,PORT=2638);ServerName=EAGLESOFT;Integrated Security = True; User ID = dba; PWD = sql"))
{
try
{
conn.Open();
using (OleDbCommand cmd = new OleDbCommand("SELECT tran_num, provider_id, tran_date FROM transactions WHERE tran_date LIKE '2015-11-23%'", conn))
{
using (OleDbDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
Console.WriteLine("{0}|{1}|{2}", reader.GetValue(0).ToString(), reader.GetValue(1).ToString(), reader.GetValue(2).ToString());
}
}
}
}
catch (Exception connerr) { Debug.WriteLine(connerr.Message); }
conn.Close();
}
if (Debugger.IsAttached)
{
Console.ReadLine();
}
}
}
}

I don't see any reason why you would be getting previous results, here. Are you running multiple instances of this code at the same time? Are you manually changing the IP address in your code each time? I assume the "Transactions" object is an actual table and not something being generated on-the-fly?
With just a tiny bit of modification, you could pass the IP address as a command line parameter:
static void Main(string[] args)
{
string ip, port = null;
for (int i = 0; i < args.Length; i++)
{
if (args[i].StartsWith("/i:"))
ip = args[i].Substring(args[i].IndexOf(':') + 1);
else if (args[i].StartsWith("/p:"))
port = args[i].Substring(args[i].IndexOf(':') + 1);
}
// Default the port value to 2638 (since I have no idea if that changes).
if (string.IsNullOrEmpty(port))
port = "2638";
string connStr = string.Format("Provider=SAOLEDB.10;LINKS=tcpip(host={0},PORT={1});ServerName=EAGLESOFT;Integrated Security = True; User ID = dba; PWD = sql", ip, port);
using (OleDbConnection conn = new OleDbConnection(connStr))
{
try
{
conn.Open();
if (conn.State != System.Data.ConnectionState.Open)
// You could also implement a WHILE loop with a small delay (~1200ms) and try again to open the connection, with a counter to "fail" after a certain number (like 3) of attempts.
throw new Exception("Unable to open connection to database.");
using (OleDbCommand cmd = new OleDbCommand("SELECT tran_num, provider_id, tran_date FROM transactions WHERE tran_date LIKE '2015-11-23%'", conn))
using (OleDbDataReader reader = cmd.ExecuteReader())
while (reader.Read())
Console.WriteLine("{0}|{1}|{2}", reader.GetValue(0).ToString(), reader.GetValue(1).ToString(), reader.GetValue(2).ToString());
}
catch (Exception connerr)
{ Debug.WriteLine(connerr.Message); }
finally
{ conn.Close(); }
}
if (Debugger.IsAttached)
{
Console.ReadLine();
}
}

First and foremost (for testing purposes, that is) I would probably try removing the ServerName parameter since you're already providing an IP address explicitly.
So your connection string would be:
Provider=SAOLEDB.10;LINKS=tcpip(host=X.X.X.X,PORT=2638);Integrated Security = True; User ID = dba; PWD = sql
Similar to ORA files, DSNs, etc, it almost sounds like you have a server alias configured for EAGLESOFT that may be overwriting the IP preference in your testing.

Make sure you change EagleSoft as well as IP. You have to pass the IP address as an arg[]. Modify code as below to allow the IP to change
string host = "X.X.X.X";
string conStr = string.Format("Provider=SAOLEDB.10;LINKS=tcpip(host={0},PORT=2638);ServerName=EAGLESOFT;Integrated Security = True; User ID = dba; PWD = sql", host);
using (OleDbConnection conn = new OleDbConnection(conStr))
​

Related

Why I cannot throw my own sql connection exception?

I'm trying to create a simple WPF application. I would like the application to indicate if it is not connected to the database, so that it cannot send requests and perform a check of its connection. Simply throw and catch the exception, which will be printed on the screen
My IsConnected method:
public static bool IsConnected(SqlConnection conn)
{
bool isConnected = false;
try
{
if (conn == null)
{
throw new ConnectionException("It is not possible to connect to the database. Please check your settings and try again");
}
else
{
isConnected = true;
}
}
catch (ConnectionException ex)
{
MessageBox.Show(ex.Message);
}
return isConnected;
}
Where I am using this IsConnected() method:
public User UserLogin(string email, string password)
{
query = #"SELECT * FROM [User] WHERE email = #email AND password = #password";`
User user = null;
try
{
using (SqlConnection conn = new SqlConnection(DatabaseSingleton.connString))
{
if (DatabaseSingleton.IsConnected(conn))
{
using (SqlCommand command = new SqlCommand(query, conn))
{
conn.Open();
command.Parameters.Add("#email", SqlDbType.VarChar, 50).Value = email;
command.Parameters.Add("#password", SqlDbType.VarChar, 50).Value = password;
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
user = new User
{
Id = reader.GetInt32(0),
Name = reader.GetString(1),
Second_name = reader.GetString(2),
Email = reader.GetString(3),
Password = reader.GetString(4),
User_type = (Type_Of_User)Enum.ToObject(typeof(Type_Of_User), reader.GetInt32(5))
};
}
reader.Close();
}
}
}
}
catch (InvalidInput e)
{
MessageBox.Show(e.Message);
}
return user;
}
Your approach is inherently sub optimal due to the way database access works. ADO should in any case throw an error if it times out.
When you try and connect with
SqlConnection conn = new SqlConnection
That will try and connect for a default period before it times out. I think that's 30 seconds. You may over ride that in your connection string.
https://learn.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlconnection.connectiontimeout?view=dotnet-plat-ext-7.0
You could initially set that to say 2 seconds and reduce the wait. That's still 2 seconds though and maybe your database will be a bit slow one day.
If a database server may or may not be available then you can first try using ping to see if the server is there and working.
Using ping in c#
When you try and do anything with a database there will be a latency. You send a request off. The dbms receives it. goes and gets your data and returns it.
Most of the latency is usually down to things happening on the database server.
You should free up your ui thread by doing all database access on another thread and returning the results. You should use async methods for all db access including opening the database.
eg
OpenAsync
https://learn.microsoft.com/en-us/dotnet/api/system.data.common.dbconnection.openasync?view=net-7.0
Rather than voids use async Task for your database access.
https://www.pluralsight.com/guides/using-task-run-async-await

Xamarin MysqlConnector weird NullReferenceException error

I'm wanting to make a small and simple mobile app for a school project, I know connecting to a db from a phone is not good for security reasons but basically only I will touch it.
So to connect my Xamarin app to Mysql I downloaded the extension MysqlConnector (https://www.nuget.org/packages/MySqlConnector/2.1.8?_src=template)
Everything seemed to work at first, but now I think that there is a problem in their library that is not compatible with Xamarin:
I seem to always get a nullreference exception at the second query at line
reader = cmd.ExecuteReader();. I don't know why, nothing is null, I've printed everything.
(I've put a comment on the line where it happens) I seriously doubt it is a problem in their library since they have 37.2M downloads in total. But maybe it is just a compatability conflict, but that makes it odd that the first query works then.
Here is all my current code:
using PuppyChinoBestelling.Views;
using System;
using System.Collections.Generic;
using System.Text;
using Xamarin.Forms;
using MySqlConnector;
using System.Threading.Tasks;
namespace PuppyChinoBestelling.ViewModels
{
public class LoginViewModel : BaseViewModel
{
public Command LoginCommand { get; }
public string Mail { get; set; }
public string Pass { get; set; }
public LoginViewModel()
{
Pass = string.Empty;
Mail = string.Empty;
LoginCommand = new Command(OnLoginClicked);
}
private async void OnLoginClicked(object obj)
{
MySqlConnection conn = new MySqlConnection("private");
try
{
conn.Open();
Console.WriteLine("Conn opened!");
}
catch(Exception ex)
{
Console.WriteLine("Error " + ex.Message);
}
string sql = #"SELECT * FROM users WHERE email = #email;";
var cmd = conn.CreateCommand();
cmd.CommandText = sql;
cmd.Parameters.AddWithValue("#email", Mail);
var reader = cmd.ExecuteReader();
if (reader.HasRows)
{
sql = #"SELECT * FROM users WHERE email = #email;";
cmd = conn.CreateCommand();
cmd.Parameters.Clear();
cmd.CommandText = sql;
cmd.Parameters.AddWithValue("#email", Mail);
reader = cmd.ExecuteReader(); //null reference happening here idk why
string pwdHashed = reader.GetString(5);
bool validPwd = BCrypt.Net.BCrypt.Verify(Pass, pwdHashed);
conn.Close();
if (validPwd)
{
await Shell.Current.GoToAsync($"//{nameof(AboutPage)}");
}
else
{
Console.WriteLine("Foute logingegevens!");
}
}
else
{
Console.WriteLine("Je bestaat niet!");
}
}
}
}
Thanks in advance!
It's hard to say for certain, but it's likely the issue is because you are not closing the reader and command, and you can't have multiple commands on the same connection.
Also, you need to advance the reader using reader.Read.
In any case there is no need to run the command twice in the first place. You already had all the information on the first run.
You also need to dispose everything with using. This automatically closes the connection.
Don't SELECT *, just select the columns you need.
Ideally, you would calculate the hash for the given password, and send it to the database server to check, rather than pulling out the real password hash from the database (could be a security risk).
Don't store hashes as strings. Instead store them as binary with the varbinary data type, and cast to byte[] on the C# side.
Unclear why you are handling errors only for opening the connection, not for executing the command.
private async void OnLoginClicked(object obj)
{
const string sql = #"
SELECT Pass
FROM users
WHERE email = #email;
";
using (var conn = new MySqlConnection("private"))
using (var cmd = new MySqlCommand(sql, conn))
{
try
{
conn.Open();
Console.WriteLine("Conn opened!");
}
catch(Exception ex)
{
Console.WriteLine("Error " + ex.Message);
return; // no point continuing
}
cmd.Parameters.AddWithValue("#email", Mail);
using (var reader = cmd.ExecuteReader())
{
if (!reader.Read())
{
Console.WriteLine("Je bestaat niet!");
return; // no point continuing
}
string pwdHashed = (string)reader["Pass"];
conn.Close();
bool validPwd = BCrypt.Net.BCrypt.Verify(Pass, pwdHashed);
if (validPwd)
{
await Shell.Current.GoToAsync($"//{nameof(AboutPage)}");
}
else
{
Console.WriteLine("Foute logingegevens!");
}
}
}
}
An alternative method is to remove the reader altogether and use ExecuteScalar
private async void OnLoginClicked(object obj)
{
const string sql = #"
SELECT Pass
FROM users
WHERE email = #email;
";
using (var conn = new MySqlConnection("private"))
using (var cmd = new MySqlCommand(sql, conn))
{
try
{
conn.Open();
Console.WriteLine("Conn opened!");
}
catch(Exception ex)
{
Console.WriteLine("Error " + ex.Message);
return; // no point continuing
}
cmd.Parameters.AddWithValue("#email", Mail);
string pwdHashed = cmd.ExecuteScalar() as string;
conn.Close();
if (pwdHashed is null)
{
Console.WriteLine("Je bestaat niet!");
return; // no point continuing
}
bool validPwd = BCrypt.Net.BCrypt.Verify(Pass, pwdHashed);
if (validPwd)
{
await Shell.Current.GoToAsync($"//{nameof(AboutPage)}");
}
else
{
Console.WriteLine("Foute logingegevens!");
}
}
}

SQL Ntext Items Only Having the First Two Chars Read in

I am currently programming a C# program that lets students log into an interface, check grades, etc.. Admins can create new users. The student IDs are 9-digit codes that all begin with "95." When an admin is creating a new user, I want to go through the database to make sure that the ID number they have entered isn't already taken.
To do this, I have the following code:
connection.Open();
readerUsers = commandUsers.ExecuteReader();
while (readerUsers.Read())
{
MessageBox.Show(readerUsers[2].ToString());
if(readerUsers[2].ToString() == IDNum)
{
userAlreadyExists = true;
break;
}
}
connection.Close();
And in my Users table, which readerUsers and commandUsers are connected to, I have the following:
IDuser Username 95Number Password Active Admin
-------------------------------------------------------------
1 sward 951619984 uo99lb True True
... ... ... ... ... ...
Now, when I went to test my code by creating a user with the ID number of 951619984 (a number already entered in the database), userAlreadyExists would still remain false. So I made the program show a message box of each item in the 95Number column (which is of type Ntext). Every time, the message box would only show "95".
I am very new to programming with databases, so I apologize if this is a very newby question, but I'm not sure what to do to get the whole string from this ntext column. Could someone explain what I'm doing wrong? Thank you for your time.
Here is a better way of doing that:
var connstr = ConfigurationManager.ConnectionStrings["your key"].ConnectionString;
var sql = "SELECT COUNT(*) FROM Users WHERE [95number]=#num";
using (var conn = new SqlConnection(connstr))
using (var cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add("num",SqlDbType.Int).Value = IDNum;
conn.Open();
var result = cmd.ExecuteScalar();
userAlreadyExists = result > 0;
}
I did mines this way.
string Qstring = "Select 95number where 95number = '95#########'";
using (SqlConnection Con = new SqlConnection(Form1.ConnectionStringGen))
using (SqlCommand Com = con.CreateCommand())
{
Com.CommandText = Qstring;
con.Open();
using (SqlDataReader Reader = Com.ExecuteReader())
{
if(Reader.Read())
{
string 95Numb = Reader["95Number"].ToString();
Messagebox.show(95Numb);
userAlreadyExists = true;
//meaning if the reader reads an item it will prompt
}
else
{
userAlreadyExists = false;
}
}
con.Close();
}
}
catch (Exception)
{
throw;
}

SQL Server connections in ASP.NET application [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I have created a web application with asp.net, roughly 100 users are using it.
However from time to time people are getting the error message that the connection is still open. Indicating that it was not closed properly.
It appears on random places, not one specific place and no other errors before it.
I know that when I have a bug in the application and it crashes without me gracefully dealing with the error the connection remains open as well and basically everyone will crash because of it. This made me think that everyone uses the same connection object, is it possible that 2 users might have the perfect timing and invoke a function using a DB connection at the same time causing the error? Is there a way to make sure everyone uses their own connection objects, like put it in their session or something?
I hope you can understand what I mean, I don't think posting any of my code will help since it happens on random places within my project.
They are connection to a SQL Server using System.Data.SqlClient.
Find below the function which generates the error. This function is called by the Page_Load, nothing is before it.
public static SqlConnection conn = new SqlConnection("Data Source=Server00\\SQLEXPRESS;Initial Catalog=r2;Integrated Security=true;Connect Timeout=0");
private void populateGameDrop()
{
try
{
conn.Open();
drop_game.Items.Clear();
SqlCommand cmd = conn.CreateCommand();
Access ac = (Access)Session["Access"];
cmd.CommandText = "Select * from dbo.Games where " + ac.GameQuery;
SqlDataReader r = cmd.ExecuteReader();
while (r.Read())
{
drop_game.Items.Add(new ListItem(r["name"].ToString(), r["Abbr"].ToString()));
}
conn.Close();
}
catch (Exception exc)
{
conn.Close();
Log.Error(exc.ToString());
Session["Error"] = exc.ToString();
Response.Redirect("~/YouBrokeIt.aspx");
}
populateServers();
SetSplitScreen();
}
Don't try to share SqlConnection objects.
Try this instead:
private static string connString = "Data Source=Server00\\SQLEXPRESS;Initial Catalog=r2;Integrated Security=true;Connect Timeout=0";
private void populateGameDrop()
{
try
{
using (var conn = new SqlConnection(connString))
{
conn.Open();
drop_game.Items.Clear();
using (var cmd = conn.CreateCommand())
{
Access ac = (Access)Session["Access"];
//TODO
//TODO - Introduce parameters to avoid SQL Injection risk
//TODO
cmd.CommandText = "Select name,Abbr from dbo.Games where " + ac.GameQuery;
using(SqlDataReader r = cmd.ExecuteReader())
{
while (r.Read())
{
drop_game.Items.Add(new ListItem(r["name"].ToString(),
r["Abbr"].ToString()));
}
}
}
}
}
catch (Exception exc)
{
Log.Error(exc.ToString());
Session["Error"] = exc.ToString();
Response.Redirect("~/YouBrokeIt.aspx");
}
populateServers();
SetSplitScreen();
}
Behind the scenes, .NET uses a concept called connection pooling so that the actual number of real connections to SQL Server are minimized. But SqlConnection objects aren't designed to be shared by multiple threads.
Don't place your database code directly in your ASPX pages. Creating an extra layer (i.e. DAL) allows you to test the DB methods without using the page.
Try something like this.
//Don't embed database logic directly in the aspx files
public class GamesProvider
{
//Put the ConnectionString in you configuration file
private string ConnectionString
{
get { return ConfigurationManager.ConnectionStrings["GameDB"].ConnectionString; }
}
public IEnumerable<Game> LoadGames(string x, string y)
{
var games = new List<Game>();
const string queryString = "select name, Abbr from dbo.Games where x = #x and y = #y";
using (var connection = new SqlConnection(ConnectionString))
using (var command = new SqlCommand(queryString, connection))
{
command.Parameters.AddWithValue("#x", x);
command.Parameters.AddWithValue("#y", y);
using (var dateReader = command.ExecuteReader())
{
while (dateReader.Read())
{
var game = new Game
{
Name = dateReader["name"].ToString(),
Abbr = dateReader["Abbr"].ToString(),
};
games.Add(game);
}
}
}
return games;
}
}
//Use types
public class Game
{
public string Name { get; set; }
public string Abbr { get; set; }
}
Your SQL connections shouldn't be static, use the following to create them
var connectionString = "YOUR CONNECTION STRING";
var queryString = "SQL QUERY";
using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand(queryString, connection))
using (SqlDataReader dateReader = command.ExecuteReader()) {
}
VERY IMPORTANT
You should use parameterised SQL your code is open to SQL injection attacks.
please see Parameterize SQL query

reader only pulling one row in while loop C#

I have two problems. One is that it is only pulling one row and sending it to ms fax when there are a few hundred to be sent. The other is that it doesn't pull any more after that first and it throws an error. I thought I was closing out my connections. I don't understand what the problem is. I have included the code and error.
Service1.cs
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 MySql.Data.MySqlClient;
using FAXCOMLib;
using FAXCOMEXLib;
namespace ProcessFaxes
{
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}
public static Timer timer = new Timer();
protected override void OnStart(string[] args)
{
timer.Elapsed += new ElapsedEventHandler(Tick);
timer.Interval = 600000; // every 10 minutes
timer.Enabled = true;
// Console.ReadLine();
}
protected override void OnStop()
{
}
public static void Tick(object source, ElapsedEventArgs e)
{
string connString = "Server=localhost;Port=3306;Database=communications;Uid=root;password=pass;";
MySqlConnection conn = new MySqlConnection(connString);
MySqlCommand command = conn.CreateCommand();
MySqlConnection connupdate = new MySqlConnection(connString);
MySqlCommand commandupdate = connupdate.CreateCommand();
command.CommandText = "SELECT * FROM outbox WHERE `faxstat` = 'Y' AND `fax` <> '' AND `faxpro` = 'PENDING'";
//command.CommandText = "UPDATE blah blah";
//conn.Open();
//conn.ExecuteNonQuery();
//conn.Close();
try
{
conn.Open();
connupdate.Open();
}
catch (Exception ex)
{
// Console.WriteLine(Ex.Message);
LogException(ex.ToString());
throw; // or whatever you want to do with it
}
MySqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
//Console.WriteLine(reader["filepath"].ToString());
SendFax(reader["id"].ToString(), reader["filepath"].ToString(), #"C:\FAXDOC\" + reader["filepath"].ToString(), reader["account"].ToString(), reader["fax"].ToString(), reader["fax_orig"].ToString());
string id = reader["id"].ToString();
commandupdate.CommandText = "UPDATE outbox SET `faxpro` = 'DONE' WHERE `id` = '" + id + "'";
commandupdate.ExecuteNonQuery();
}
}
conn.Close();
connupdate.Close();
}
public static void SendFax(string DocumentId, string DocumentName, string FileName, string RecipientName, string FaxNumber, string RecipientHomePhone2)
{
if (FaxNumber != "")
{
try
{
FAXCOMLib.FaxServer faxServer = new FAXCOMLib.FaxServerClass();
faxServer.Connect(Environment.MachineName);
FAXCOMLib.FaxDoc faxDoc = (FAXCOMLib.FaxDoc)faxServer.CreateDocument(FileName);
faxDoc.RecipientName = RecipientName;
faxDoc.FaxNumber = FaxNumber;
faxDoc.BillingCode = DocumentId;
faxDoc.DisplayName = DocumentName;
faxDoc.RecipientHomePhone = RecipientHomePhone2;
int Response = faxDoc.Send();
faxServer.Disconnect();
}
catch (Exception Ex) {
// Console.WriteLine(Ex.Message);
LogException(Ex.ToString());
throw; // or whatever you want to do with it
}
}
}
public static void LogException(string ErrorDescription)
{
// The name of our log in the event logs
string Log = "Process Faxes";
// Check to see fi the log for AspNetError exists on the machine
// If not, create it
if ((!(EventLog.SourceExists(Log))))
{
EventLog.CreateEventSource(Log, Log);
}
// Now insert your exception information into the AspNetError event log
EventLog logEntry = new EventLog();
logEntry.Source = Log;
logEntry.WriteEntry(ErrorDescription, EventLogEntryType.Error);
}
}
}
error
Event Type: Error
Event Source: Process Faxes
Event Category: None
Event ID: 0
Date: 3/6/2012
Time: 2:01:06 PM
User: N/A
Computer: FAXSERVER
Description:
MySql.Data.MySqlClient.MySqlException (0x80004005): Too many connections
at MySql.Data.MySqlClient.MySqlStream.ReadPacket()
at MySql.Data.MySqlClient.NativeDriver.Open()
at MySql.Data.MySqlClient.Driver.Open()
at MySql.Data.MySqlClient.Driver.Create(MySqlConnectionStringBuilder settings)
at MySql.Data.MySqlClient.MySqlPool.GetPooledConnection()
at MySql.Data.MySqlClient.MySqlPool.TryToGetDriver()
at MySql.Data.MySqlClient.MySqlPool.GetConnection()
at MySql.Data.MySqlClient.MySqlConnection.Open()
at ProcessFaxes.Service1.Tick(Object source, ElapsedEventArgs e) in C:\Documents and Settings\bruser\My Documents\Visual Studio 2010\Projects\ProcessFaxes\ProcessFaxes\Service1.cs:line 56
I think you should refactor a bit. I explained a little in a comment above, but here's how I would change it (I added some comments for you too):
public static void Tick(object source, ElapsedEventArgs e)
{
// Prevent another Tick from happening if this takes longer than 10 minutes
(source as Timer).Enabled = false;
// It would be better practice to put this in a settings or config file
// so you can change it without having to recompile your application
string connString = "Server=localhost;Port=3306;Database=communications;Uid=root;password=pass;";
// I won't change them here, but since these classes implement IDisposable,
// you should be using a using statement around them:
// using (var conn = new MySqlConnection(connString))
// {
// // use conn
// }
MySqlConnection conn = new MySqlConnection(connString);
MySqlCommand command = conn.CreateCommand();
MySqlCommand updateCommand = conn.CreateCommand();
command.CommandText = "SELECT * FROM outbox WHERE `faxstat` = 'Y' AND `fax` <> '' AND `faxpro` = 'PENDING'";
try
{
conn.Open();
MySqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
SendFax(reader["id"].ToString(), reader["filepath"].ToString(), #"C:\FAXDOC\" + reader["filepath"].ToString(), reader["account"].ToString(), reader["fax"].ToString(), reader["fax_orig"].ToString());
string id = reader["id"].ToString();
// I would use a prepared statement with either this query
// or a stored procedure with parameters instead of manually
// building this string (more good practice than worrying about
// SQL injection as it's an internal app
updateCommand.CommandText = "UPDATE outbox SET `faxpro` = 'DONE' WHERE `id` = '" + id + "'";
updateCommand.ExecuteNonQuery();
}
}
}
catch (Exception ex)
{
LogException(ex.ToString());
throw;
}
finally
{
// If you're not going to use using-statements, you might want to explicitly
// call dispose on your disposable objects:
// command.Dispose();
// updateCommand.Dispose();
conn.Close();
// conn.Dispose();
}
// Enable the timer again
(source as Timer).Enabled = true;
}
As to why you're only receiving one row when you're expecting many, I suspect your SQL is at fault.
You should not be using a timer.
A timer fires at regular intervals, and does not care if the previous event has completed or not.
Look at using a Background Worker to send your faxes, having it loop over the queue, and then pause when the queue is empty.
The issue lies in your connection object. You have defined a couple of connection objects. You only need one.
Here are the two in question:
MySqlConnection connupdate = new MySqlConnection(connString);
MySqlConnection conn = new MySqlConnection(connString);
Eliminate the connection to one of them.
Here is one way to fix your code:
string connString = "Server=localhost;Port=3306;Database=communications;Uid=root;password=pass;";
using(MySqlConnection conn = new MySQLConnection(connString))
{
using(MySQlCommand command = conn.CreateCommand())
{
command.CommandText = "SELECT ...";
conn.Open();
using(MySqlDataReader reader = command.ExecuteReader())
{
//process rows...
}
}
}

Categories