c# odbcDatareader get the duplicated field value - c#

I have a strange problem:
Database: Firebird
Connection String:
Driver={Firebird/InterBase(r)driver};Dbname=xxx;CHARSET=NONE;UID=xxx;
PASSWORD=xxx
I use a set of ODBC classes to operation(select) the database table
when I loop the db records with OdbcDataReader.GetValue(), if some fields(char type) have no value(char_length()=0), it would get the last record field value; if fields has the value, it's ok(does not get the value from last record)
My code likes below:
var dr = this.SqlExecutor.Open(sql); //sql is String variable that stored the sql statement
while (dr.Read())
{
this.Logger.Info("-----Customer_Id: " + this.SqlReader.GetFieldAsString(dr, "Customer_Id") + " -----"); // this not duplicated because it's not empty
this.Logger.Info("-----Customer_Email: " + this.SqlReader.GetFieldAsString(dr, "Customer_email") + " -----"); //this would if some records has empty value
}
// the method SqlExecutor.Open(sql) and SqlReader.GetFieldAsString() please refer to below:
public IDataReader Open(string sql)
{
this.Logger.Debug("sql: " + sql);
if (this.reader != null && !this.reader.IsClosed)
{
this.reader.Close();
this.reader = null;
}
try
{
this.cmdForSelect.Connection = this.conn;
this.cmdForSelect.CommandTimeout = 120;
this.cmdForSelect.CommandText = sql;
this.cmdForSelect.Parameters.Clear();
foreach (var p in this.dbParameters)
{
this.cmdForSelect.Parameters.Add(p);
}
this.reader = cmdForSelect.ExecuteReader();
}
catch (Exception ex)
{
this.Logger.Error("There is an error: {0}", ex.Message);
this.Logger.Info("Error sql query:" + sql);
throw;
}
finally
{
this.ClearParameters();
}
return this.reader;
}
public string GetFieldAsString(IDataReader dr, string fieldName)
{
try
{
var value = dr.GetValue(dr.GetOrdinal(fieldName));
if (value == DBNull.Value)
{
return string.Empty;
}
return Convert.ToString(value);
}
catch
{
return string.Empty;
}
}
Besides, this case is fine on my computer, just happened on my customer's computer, I feel this does not matter with mycode, anyone know this, please help me, thanks a lot!!!

Assuming the actual code is not posted in your question; I think the problem is with re-initiation of the variable in the actual code. You need to revisit the code and check the IF-ELSE condition you have applied on the this.SqlReader.GetFieldAsString(dr, "Customer_email")

Related

How to return a string back to a separate class from a method that accepts integers

I'm passing two integers to a method in another class, comparing that against a database table, and creating a string for any duplicates found. I'd like to pass that string back to the calling method/class.
In calling class:
if (IsValidMfgBadgeEntries())
{
int beginningSerial = Convert.ToInt32(txtMfgBeginning.Text);
int count = Convert.ToInt32(txtMfgCount.Text);
SerialsManufacturingDB.VerifyManufacturingSerialOnly
(count, beginningSerial);
}
In separate class:
public static VerifyManufacturingSerialOnly(int count, int beginning)
{
OleDbConnection connection = BadgeDatabaseDB.GetConnection();
string checkStatement
= "SELECT OrderNumber "
+ "FROM SerialNumbers-MFG "
+ "WHERE SerialNumber = #CurrentSerial";
OleDbCommand command =
new OleDbCommand(checkStatement, connection);
string duplicateSerials = "";
for (int i = 0; i < count; i++)
{
int currentSerial = beginning;
command.Parameters.AddWithValue("#CurrentSerial", currentSerial);
try
{
connection.Open();
OleDbDataReader dataReader =
command.ExecuteReader(CommandBehavior.SingleRow);
if (dataReader.Read())
{
duplicateSerials +=
"Serial # " +
currentSerial +
" already exists in order # " +
dataReader["OrderNumber"].ToString() + "\n";
}
else
{
;
}
}
catch (OleDbException ex)
{
throw ex;
}
finally
{
connection.Close();
}
i++;
}
//WHAT TO RETURN??
}
You must declare the method with a return type (in this case string):
public static string VerifyManufacturingSerialOnly(int count, int beginning)
At the end of the method you can write
return duplicateSerials;
You can then call the method like this:
string result = SerialsManufacturingDB.VerifyManufacturingSerialOnly(count, beginningSerial);
If you have a method which is not returning a value, you must use the type placeholder void
public void DoesNotReturnAValue()
{
...
}
In fact you can use a return statement at any place in the method. A method can have several return statements. In a void method you simply write
return;
without argument.
See also
return (C# Reference)
Return with examples at dot net perls.

How to fix a boolean method that returns true everytime asp.net

I designed my webpage to read a data string then display the results on labels in an html table. I am attempting to highlight the row that my database reads as a current order. My only problem is only one record is set to be active but they all highlight as if they were active. I use an array to set my data and I also use the label to get the ID I need (all is in code below). I have posted my method and where I use it in the asp page load. How can I fix my method to return correctly?
The implementing of the method in page load
if (lineData.IsCurrentOrderFind(L68.Text))
{
myTable.Rows[1].Cells[0].BgColor = "#FE2E2E";
myTable.Rows[1].Cells[1].BgColor = "#FE2E2E";
myTable.Rows[1].Cells[2].BgColor = "#FE2E2E";
myTable.Rows[1].Cells[3].BgColor = "#FE2E2E";
myTable.Rows[1].Cells[4].BgColor = "#FE2E2E";
}
Here is method that label above gets passed to
public bool IsCurrentOrderFind(string itemNumber)
{
StringBuilder sqlString = new StringBuilder();
sqlString.Append("SELECT * ");
sqlString.Append("FROM WorkOrder ");
sqlString.Append("WHERE LineNumber = " + ConfigurationManager.AppSettings["Line"] + " AND LineCompleted = 0 AND (ScaleGroup LIKE '%1' OR ScaleGroup LIKE '%3') ");
sqlString.Append(" AND CaseGenNum6 = #CaseGenNum6");
SqlDataReader reader = null;
SqlConnection dbConn = App_Code.DBHelper.getConnection();
SqlParameter[] parameters = new SqlParameter[] { new SqlParameter("#CaseGenNum6", itemNumber) };
try
{
reader = App_Code.DBHelper.executeQuery(dbConn, sqlString.ToString(), parameters);
while (reader.Read())
{
IsCurrentOrder = (reader["IsCurrentOrder"] != DBNull.Value && !string.IsNullOrEmpty(reader["IsCurrentOrder"].ToString())) ? true : false;
}
reader.Close();
reader.Dispose();
dbConn.Close();
dbConn.Dispose();
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (dbConn != null)
{
try { dbConn.Close(); dbConn.Dispose(); }
catch { }
}
if (reader != null)
{
try { reader.Close(); reader.Dispose(); }
catch { }
}
}
if (IsCurrentOrder == true) I realize this is not necessary
{
return true;
}
else
{
return false;
}
}
The problem could be with this expression:
!string.IsNullOrEmpty(reader["IsCurrentOrder"].ToString())
Instead of calling ToString(), try simply casting it to a string:
!string.IsNullOrEmpty((string)reader["IsCurrentOrder"])
Possibly even better (the previous line might throw an exception if it's not really a string):
!string.IsNullOrEmpty(reader["IsCurrentOrder"] as string)
The reason being is that if the string is really null, calling ToString() will return a non-null string "null".
IsCurrentOrder is not declared locally. It seems to be declared at a higher scope. When you enter this function, nothing is initializing the variable (back to false). So, it is remaining at its last setting. Try this code instead:
public bool IsCurrentOrderFind(string itemNumber)
{
bool IsCurrentOrder = false;
//and the rest of your source code
the line
IsCurrentOrder = (reader["IsCurrentOrder"] != DBNull.Value && !string.IsNullOrEmpty(reader["IsCurrentOrder"].ToString())) ? true : false;
}
It's not actually checking the value of the field, only that it's not null or empty.
Try
if(
(reader["IsCurrentOrder"] != DBNull.Value
&&
!string.IsNullOrEmpty(reader["IsCurrentOrder"].ToString()))
)
{
IsCurrentOrder = reader["IsCurrentOrder"];
}
else
IsCurrentOrder = false;
I think there is a lot of refactoring you could do to this method though that will simplify the logic.

Should I refactor this, or is my confusion cause to be cautious? [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
This SqlCe code looks awfully strange to me:
cmd.CommandText = "INSERT INTO departments ( account_id, name) VALUES (?, ?)";
foreach(DataTable tab in dset.Tables)
{
if (tab.TableName == "Departments")
{
foreach(DataRow row in tab.Rows)
{
Department Dept = new Department();
if (!ret)
ret = true;
foreach(DataColumn column in tab.Columns)
{
if (column.ColumnName == "AccountID")
{
Dept.AccountID = (string) row[column];
}
else if (column.ColumnName == "Name")
{
if (!row.IsNull(column))
Dept.AccountName = (string) row[column];
else
Dept.AccountName = "";
}
}
List.List.Add(Dept);
. . .
dSQL = "INSERT INTO departments ( account_id, name) VALUES ('" + Dept.AccountID + "','" + Dept.AccountName +"')";
if (!First)
{
cmd.Parameters[0].Value = Dept.AccountID;
cmd.Parameters[1].Value = Dept.AccountName;
}
if (First)
{
cmd.Parameters.Add("#account_id",Dept.AccountID);
cmd.Parameters.Add("name",Dept.AccountName);
cmd.Prepare();
First = false;
}
if (frmCentral.CancelFetchInvDataInProgress)
{
ret = false;
return ret;
}
try
{
dbconn.DBCommand( cmd, dSQL, true );
}
. . .
public void DBCommand(SqlCeCommand cmd, string dynSQL, bool Silent)
{
SqlCeTransaction trans = GetConnection().BeginTransaction();
cmd.Transaction = trans;
try
{
cmd.ExecuteNonQuery();
trans.Commit();
}
catch (Exception ex)
{
try
{
trans.Rollback();
}
catch (SqlCeException)
{
// Handle possible exception here
}
MessageBox.Show("DBCommand Except 2"); // This one I haven't seen...
WriteDBCommandException(dynSQL, ex, Silent);
}
}
My questions are:
1) Should "?" really be used in the assignment to cmd.CommandText, or should "#" be used instead?
2) One of the "cmd.Parameters.Add()"s (account_id) uses a "#" and the other (name) doesn't. Which way is right, or is the "#" optional?
3) I can't make heads or tails of why DBCommand() is written as it is - the final two args are only used if there's an exception...???
I'm tempted to radically refactor this code, because it seems so bizarre, but since I don't really understand it, that might be a recipe for disaster...
I'm fairly certain this article will answer some of your questions:
http://msdn.microsoft.com/en-us/library/yy6y35y8.aspx
The second chart explains the difference between the named and positional (?) parameters (used in OleDb and ODBC).
I believe in the case where the ? is used, the # is optional, but I'm not sure of this. If it's working, I'd say that that IS the case.
The stuff in DBCommand appears to simply be there for logging purposes. If the exection fails, it tries to do a rollback and then logs the exception with the sql command (in dynSQL).
The ? parameter is older Access syntax.
My guess is this used to be an Access database, but someone converted it to SQL CE at some point.
Generally, SQL understands that ? parameter, but it's better to just change that while you are in there so that it is more understood.
I'm still trying to make heads & tails of all these variables. If I get it sorted out, I'll post up compilable (sp?) code.
EDIT: I had to put this into a method and work out all of the RED errors to make sure I wasn't giving you something that would not compile.
I passed it your DataSet like so, with lots of comments added:
private bool StrangeSqlCeCode(DataSet dset) {
const string ACCOUNT_ID = "AccountID";
const string DEPARTMENTS = "Departments";
const string NAME = "Name";
const string SQL_TEXT = "INSERT INTO departments (account_id, name) VALUES (#account_id, #name)";
bool ret = false;
//bool First = false; (we don't need this anymore, because we initialize the SqlCeCommand correctly up front)
using (SqlCeCommand cmd = new SqlCeCommand(SQL_TEXT)) {
// Be sure to set this to the data type of the database and size field
cmd.Parameters.Add("#account_id", SqlDbType.NVarChar, 100);
cmd.Parameters.Add("#name", SqlDbType.NVarChar, 100);
if (-1 < dset.Tables.IndexOf(DEPARTMENTS)) {
DataTable tab = dset.Tables[DEPARTMENTS];
foreach (DataRow row in tab.Rows) {
// Check this much earlier. No need in doing all the rest if a Cancel has been requested
if (!frmCentral.CancelFetchInvDataInProgress) {
Department Dept = new Department();
if (!ret)
ret = true;
// Wow! Long way about getting the data below:
//foreach (DataColumn column in tab.Columns) {
// if (column.ColumnName == "AccountID") {
// Dept.AccountID = (string)row[column];
// } else if (column.ColumnName == "Name") {
// Dept.AccountName = !row.IsNull(column) ? row[column].ToString() : String.Empty;
// }
//}
if (-1 < tab.Columns.IndexOf(ACCOUNT_ID)) {
Dept.AccountID = row[ACCOUNT_ID].ToString();
}
if (-1 < tab.Columns.IndexOf(NAME)) {
Dept.AccountName = row[NAME].ToString();
}
List.List.Add(Dept);
// This statement below is logically the same as cmd.CommandText, so just don't use it
//string dSQL = "INSERT INTO departments ( account_id, name) VALUES ('" + Dept.AccountID + "','" + Dept.AccountName + "')";
cmd.Parameters["#account_id"].Value = Dept.AccountID;
cmd.Parameters["#name"].Value = Dept.AccountName;
cmd.Prepare(); // I really don't ever use this. Is it necessary? Perhaps.
// This whole routine below is already in a Try/Catch, so this one isn't necessary
//try {
dbconn.DBCommand(cmd, true);
//} catch {
//}
} else {
ret = false;
return ret;
}
}
}
}
return ret;
}
I wrote an overload for your DBCommand method to work with Legacy code:
public void DBCommand(SqlCeCommand cmd, string dynSQL, bool Silent) {
cmd.CommandText = dynSQL;
DBCommand(cmd, Silent);
}
public void DBCommand(SqlCeCommand cmd, bool Silent) {
string dynSQL = cmd.CommandText;
SqlCeTransaction trans = GetConnection().BeginTransaction();
cmd.Transaction = trans;
try {
cmd.ExecuteNonQuery();
trans.Commit();
} catch (Exception ex) {
try {
trans.Rollback(); // I was under the impression you never needed to call this.
// If Commit is never called, the transaction is automatically rolled back.
} catch (SqlCeException) {
// Handle possible exception here
}
MessageBox.Show("DBCommand Except 2"); // This one I haven't seen...
//WriteDBCommandException(dynSQL, ex, Silent);
}
}

Write & Read App Config Setting

I have an application that need to check to the database if a particular code exists; if it does exist, then have to load the corresponding value of that code else return null.
I don't want to hit the database for each code(running about 200.000 codes ).
so i got this small app to test the app.conf
public static void setAppSetting(string key, string value)
{
Configuration config = ConfigurationManager.OpenExeConfiguration(System.Reflection.Assembly.GetExecutingAssembly().Location);
if (config.AppSettings.Settings != null)
{
config.AppSettings.Settings.Remove(key);
}
config.AppSettings.Settings.Add(key, value);
config.Save(ConfigurationSaveMode.Modified);
}
public static string getAppSetting(string key)
{
try
{
Configuration config = ConfigurationManager.OpenExeConfiguration(System.Reflection.Assembly.GetExecutingAssembly().Location);
return config.AppSettings.Settings[key].ToString();
}
catch (Exception ex)
{
throw ex;
}
}
private static void loadKeysValues()
{
using (SqlConnection Gcon = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["constr"].ConnectionString))
{
//Open Connection
Gcon.Open();
using (SqlCommand sqlCmd = new SqlCommand("SELECT key,value FROM tables", Gcon))
{
using (SqlDataReader reader = sqlCmd.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
System.Console.WriteLine(reader.GetString(0) + " , " + reader.GetString(1));
setAppSetting(reader.GetString(0), reader.GetString(1));
}
}
} // End of SqlDataReader
} // end of SqlCommand
}
}
static void Main(string[] args)
{
System.Console.WriteLine("Loading.........");
loadKeysValues();
System.Console.WriteLine("Completed");
System.Console.WriteLine("Input a key to get its value");
var input = System.Console.Read().ToString();
System.Console.WriteLine(getAppSetting(input));
System.Console.ReadLine();
}
But I got an error with the getAppSetting() at this line:
return config.AppSettings.Settings[key].ToString();
Error: Object reference not set to an instance of an object.
Plz help
Make sure that the value isn't null.
Try this:
if (config.AppSettings.Settings.ContainsKey(key) &&
config.AppSettings.Settings[key] != null)
{
return config.AppSettings.Settings[key].ToString();
}
Most likely you're trying to access a setting that doesn't exist. You could handle that exception in your catch block and return null in that case.
ToString() method donĀ“t return the value, try with Value property:
return config.AppSettings.Settings[key].Value;

How to move to next row in datatable if one row catches an error? C# 2.0

I am getting data from a mySql database and I am inserting it into another system. If a column has data in an incorrect format I log this and go to next row in the datatable. It works as expected but now if I have a search function in my method that gets some additional data and this function fails I want to immediately log this and go to next row. As it is now I just log it but it still gets inserted (without the value that didn't meet the search criteria).
My code:
private void updateCustomer()
{
MySqlConnection connection = new MySqlConnection("server=myServer;database=myDatabase;uid=myID;password=myPass");
MySqlCommand command = new MySqlCommand(#"mySelectCommand", connection);
DataTable customerTbl = new DataTable();
MySqlDataReader reader;
try
{
connection.Open();
reader = command.ExecuteReader();
if (reader.HasRows)
{
customerTbl.Load(reader);
}
reader.Close();
}
catch (Exception ex)
{
_out.error("Could not connect to mySql database");
}
finally
{
connection.Close();
}
foreach (DataRow row in customerTbl.Rows)
{
// Declare the customer variables
string customerID = Encoding.ASCII.GetString((byte[])row["Customer ID"]);
string ChildOf = row["Child of"].ToString();
// Create the customer object
Customer customer = new Customer();
customer.entityId = customerID;
if (ChildOf != "")
{
RecordRef parentRef = new RecordRef();
try
{
parentRef.internalId = searchCustomer(ChildOf);
}
catch
{
// If it fails here I want to log the customerID and then go to the next row in the datatable (could not find the internalid for ChildOf
_out.error(customerID + " was not updated. Error: invalid format Parent string");
}
finally
{
parentRef.typeSpecified = false;
customer.parent = parentRef;
}
}
// Invoke update() operation
WriteResponse response = _service.update(customer);
// Process the response
if (response.status.isSuccess)
{
}
else
{
_out.error(customerID + " was not updated. Error: " + getStatusDetails(response.status));
}
}
}
You need to remove the row in the catch block, and change the foreach loop to a backwards for loop to handle the removals.
I realized that I want to log the other failed fields as well. Maybe it's an inefficient way but I did something like:
bool findParent = true;
if (ChildOf != "")
{
try
{
RecordRef parentRef = new RecordRef();
parentRef.internalId = searchCustomer(ChildOf);
parentRef.typeSpecified = false;
customer.parent = parentRef;
}
catch
{
findParent = false;
_out.error(customerID + " was not inserted. Error: invalid format Parent string");
}
}
And then an if statement before trying to insert:
if (findPartner == true && findParent == true)
{
response = _service.add(customer);
// Process the response
if (response.status.isSuccess)
{
}
else
{
_out.error(customerID + " was not inserted. Error: " + getStatusDetails(response.status));
}
}
else
{
//_out.error(customerID + " was not updated. Error: " + getStatusDetails(response.status));
}
Use the row.HasError property.

Categories

Resources