Exception handling in C# with file stream and database - c#

I have this program, that I have to handle the exceptions for, but I never done it so I'm kind of confused. I'm guessing I'd have to handle exceptions like the value in the textfile is empty, there is no index, there is no "=" or the file is empty, but I don't really know how to define them or where to put them. Here is my code:
(the lines in the text file should look like this:
EMPIS_MAG_BUDOW=12
EMPIS_DESKA_FASOLKA=2
SM_PORTAL_POL1=-4
)
using System;
using FirebirdSql.Data.FirebirdClient;
using System.Collections.Generic;
using System.Linq;
using System.IO;
namespace dokselect
{
class indexstan
{
public string index;
public double standysp;
}
class WynikPorownania
{
public string Indeks;
public int Ilosc;
public override string ToString()
{
return Indeks + " : " + Ilosc;
}
}
}
class Program
{
public static void Main()
{
///////CONNECTION
string conn = "database=C:/PCBiznes/BAZA/IXION2_LOGMAG.FB;user=SYSDBA;password=masterkey;DataSource=192.168.24.112;Port=3050";
FbConnection myConnection = new FbConnection(conn);
FbDataReader myReader = null;
string sql = "select KARTOTEKA.indeks, STANMAG.standysp FROM kartoteka JOIN stanmag using(ID_KARTOTEKA);";
FbCommand myCommand = new FbCommand(sql, myConnection);
myConnection.Open();
myReader = myCommand.ExecuteReader();
///////LIST lista1
List<indexstan> listadb = new List<indexstan>();
double standysp;
string index;
while (myReader.Read())
{
index = myReader[0].ToString();
standysp = Convert.ToDouble(myReader[1]);
listadb.Add(new indexstan { index=index, standysp=standysp });
//Console.WriteLine(myReader[0].ToString());
}
myConnection.Close();
Console.WriteLine(listadb.Count);
//RETURN STANDYSP FUNCTION
double zwr(string myIndex)
{
var result = listadb.FirstOrDefault(listadb => listadb.index == myIndex).standysp;
return result;
}
//zwr("EMPIS_DESKA_FASOLKA");
//READ FROM TXT AND RETURN HIGHER
string path = "C:/Users/Praktykant/Documents/textdocs/dok1.txt";
List<WynikPorownania> listatf = File.ReadAllLines(path).Select(line =>
{
var linia = line.Split("=");
string index = linia[0];
int value = int.Parse(linia[1]);
return new WynikPorownania {Indeks = index, Ilosc = (int)Math.Max(value, zwr(index))};
}).ToList();
//DISPLAY ALL LISTATF CLASSES
foreach(object WynikPorownania in listatf)
{
Console.WriteLine(WynikPorownania);
}
}
}
}
I tried to make an exception like this, if the value is not given but it doesn't work and the program still collapses when the value in the text file is empty
List<WynikPorownania> listatf = File.ReadAllLines(path).Select(line =>
{
var linia = line.Split("=");
string index = linia[0];
if (linia[1] == "")
{
throw new Exception("Is empty ... or whatever you caught");
return null;
}
else
{
int value = int.Parse(linia[1]);
}
return new WynikPorownania { Indeks = index, Ilosc = (int)Math.Max(value, zwr(index)) };
}).ToList();

To handle exceptions in C# you should use try catch (see c# refence try-catch-finally)
In your code I suggest to wrap a try catch around the firebird connection, since you are depending on this:
try {
// your code
} catch (Exception ex) {
// define what happens if exception is thrown
}
Its key that you include for instance the firebird connection and the while loop into the try, since those are things your code is depending on.
To handle the value in the text file:
//DISPLAY ALL LISTATF CLASSES
// note that I have replaced the "object" with your class.
foreach(WynikPorownania wynikPorownania in listatf)
{
if (wynikPorownania.Indeks != ... || wynikPorownania.Ilosc != ... )
throw new Exception("Is empty ... or whatever you caught");
Console.WriteLine(wynikPorownania);
}

//try something like below.
class Program
{
public static void Main()
{
//CONNECTION
try
{
//... <YOUR CODE>
//DISPLAY ALL LISTATF CLASSES
foreach(object WynikPorownania in listatf)
{
Console.WriteLine(WynikPorownania);
/*if <your condition>
{
throw <your exception1>
}
else if <your condition>
{
throw <your exception1>
}*/
}
}
catch (Exception <your Exception>)
{
// Throw the message
// Or return the code
}
}
}

Related

Text file input exception handling C#

I have this program that takes data from a database, puts it into a list, than reads data from a text file, compares two values - one from the text file and one from the database - according to a given index, and returns the higher value to another list. My problem is I can't handle the problem, when a line in the text file is missing an index. When calling function "zwr(index)", it gives a NullReferenceException, but I don't know how to handle it, typing catch nullreferenceexception at the bottom doesn't work and really I don't know where to go from now. I also have to make it so it doesn' crash when the user puts a wrong index. Here is my code, hope somebody can help:
using System;
using FirebirdSql.Data.FirebirdClient;
using System.Collections.Generic;
using System.Linq;
using System.IO;
namespace dokselect
{
class indexstan
{
public string index;
public double standysp;
}
class WynikPorownania
{
public string Indeks;
public int Ilosc;
public override string ToString()
{
return Indeks + " : " + Ilosc;
}
}
class Program
{
public static void Main()
{
try
{
///////CONNECTION
string conn = "database=C:/PCBiznes/BAZA/IXION2_LOGMAG.FB;user=SYSDBA;password=masterkey;DataSource=192.168.24.112;Port=3050";
FbConnection myConnection = new FbConnection(conn);
FbDataReader myReader = null;
string sql = "select KARTOTEKA.indeks,STANMAG.standysp FROM kartoteka INNER JOIN stanmag using(ID_KARTOTEKA) WHERE stanmag.ID_MAGAZYN=10002;";
FbCommand myCommand = new FbCommand(sql, myConnection);
myConnection.Open();
myReader = myCommand.ExecuteReader();
///////LIST lista1
List<indexstan> listadb = new List<indexstan>();
double standysp;
string index;
while (myReader.Read())
{
index = myReader[0].ToString();
standysp = Convert.ToDouble(myReader[1]);
if(standysp<0)
{
standysp = 0;
}
listadb.Add(new indexstan { index=index, standysp=standysp });
//Console.WriteLine(myReader[0].ToString());
}
myConnection.Close();
Console.WriteLine(listadb.Count);
//RETURN STANDYSP FUNCTION
double zwr(string myIndex)
{
var result = listadb.FirstOrDefault(listadb => listadb.index == myIndex).standysp;
return result;
}
//zwr("EMPIS_DESKA_FASOLKA");
//READ FROM TXT AND RETURN HIGHER
string path = "C:/Users/Praktykant/Documents/textdocs/dok1.txt";
List<WynikPorownania> listatf = File.ReadAllLines(path).Select(line =>
{
var linia = line.Split("=");
string index = linia[0];
int value = int.Parse(linia[1]);
if(value<0)
{
value = 0;
}
return new WynikPorownania { Indeks = index, Ilosc = (int)Math.Max(value, zwr(index)) };
}).ToList();
//DISPLAY ALL LISTATF CLASSES
foreach (WynikPorownania WynikPorownania in listatf)
{
Console.WriteLine(WynikPorownania);
}
}
catch (FileNotFoundException ex)
{
Console.WriteLine("Nie znaleziono pliku z podanej sciezki: "+ex);
}
catch (FormatException ex)
{
Console.WriteLine("Podaj indeksy i wartosci w formacie 'indeks=wartosc'. Blad zwrocil: "+ex);
}
catch (NullReferenceException ex)
{
Console.WriteLine("Nie podales prawidlowego indeksu. Blad zwrocil: "+ex);
return;
}
}
}
}
Handling the exception this way:
double zwr(string myIndex)
{
var result = listadb.FirstOrDefault(listadb => listadb.index == myIndex)?.standysp;
return result ?? 0;
}
Gets rid of the error, but still puts the data in the list resulting in something like this:
EMPIS_MAG_BUDOW : 12
: 8 <-Here is where the index wasn't given in the text file
SM_PORTAL_POL1 : 0
And I need it to stop compiling if the index is not given, cause this code will be later a part of a bigger program and this one block of code cannot collapse the whole thing. I tried using diffrent if statements in the function that returns data to the list and tried to throw in exceptions but nothing seemed to work...
Handle it this way:
double zwr(string myIndex)
{
var result = listadb.FirstOrDefault(listadb => listadb.index == myIndex)?.standysp;
return result ?? 0;
}
You are getting the exception, because listadb.FirstOrDefault(listadb => listadb.index == myIndex) is null and you are trying to access .standysp; of null.
So use the ?. which will access the previous statement only when it is not null or return null itself.
The ?? returns the left side if not null and the right side if the left one is null.

SQLite table doesn't get updated

I have a problem. I created a SwitchButton and want to store the state in a database table. So I created this code to debug:
SettingSwitch.CheckedChange += (s, b) =>
{
SettingDb testsetting = new SettingDb
{
Name = mItems[position].Name,
};
SettingDb test = MainActivity.db.SelectRowFromTableSettings(testsetting);
if (test != null)
{
bool SwitchValueBool = Convert.ToBoolean(test.Value);
}
bool isChecked = ValueDictionary[position];
if(isChecked == true)
{
isChecked = false;
}
else if(isChecked == false)
{
isChecked = true;
}
SettingDb setting = new SettingDb()
{
Name = SettingName.Text,
Type = "Switch",
Value = isChecked.ToString()
};
MainActivity.db.UpdateTableSettings(setting);
ValueDictionary[position] = isChecked;
SettingDb test2 = MainActivity.db.SelectRowFromTableSettings(testsetting);
if (test2 != null)
{
bool SwitchValueBool = Convert.ToBoolean(test2.Value);
}
};
The expected outcome should be:
test.Value = False
test2.Value = Opposite of test.Value, so True
But now the value I get from the table is always False. Here is the update function:
string folder = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
public bool UpdateTableSettings(SettingDb setting)
{
try
{
using (var connection = new SQLiteConnection(System.IO.Path.Combine(folder, "Settings.db")))
{
connection.BeginTransaction();
connection.Query<SettingDb>("UPDATE SettingDb SET Value=? WHERE Name=?", setting.Value, setting.Name);
//connection.Update(setting);
connection.Commit();
return true;
}
}
catch (SQLiteException ex)
{
Log.Info("SQLiteEx", ex.Message);
return false;
}
}
public SettingDb SelectRowFromTableSettings(SettingDb setting)
{
try
{
using (var connection = new SQLiteConnection(System.IO.Path.Combine(folder, "Settings.db")))
{
return connection.Query<SettingDb>("SELECT * FROM SettingDb WHERE Name=?", setting.Name).FirstOrDefault();
}
}
catch (SQLiteException ex)
{
Log.Info("SQLiteEx", ex.Message);
return null;
}
}
The table value doesn't get updated!!!
Can someone tell me what I am doing wrong?
Please let me know!
According to your description, you want to update sqlite database table, please take a look the following code and modify the update function.
static void UpdateDatabase(int primaryKey, string newText, int newValue)
{
string path = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments), "mydatabase.db");
var db = new SQLiteConnection(path, false);
string sql = "UPDATE MyTable SET MyTextColumn = ?, MyValueColumn = ? WHERE MyPrimaryKey= ?";
string[] parms = new String[] { newText, newValue.ToString(), primaryKey.ToString() };
var cmd = db.CreateCommand(sql, parms);
cmd.ExecuteNonQuery();
}

Mismatch in .NET metadata for SQL DateTime2 type

I'm getting a thrown exception when attempting to import a SqlDataRecord with a DateTime2 data type. There is no exception thrown in this snippet, but the cause of the later exception is evident in the following code.
using System;
using Microsoft.SqlServer.Server;
using System.Data.SqlClient;
using System.Data;
using System.Web.UI.WebControls;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Diagnostics;
namespace Testing123
{
public class Program
{
public static object SQLTParser(SqlMetaData smd, string val)
{
TypeCode systc = Parameter.ConvertDbTypeToTypeCode(smd.DbType);
try
{
return Convert.ChangeType(val, systc);
}
catch (Exception ex)
{
if (ex is InvalidCastException || ex is FormatException || ex is OverflowException)
{
Console.WriteLine("Exception reached casting " + val + " to " + Type.GetType("System." + Enum.GetName(typeof(TypeCode), systc)) + ": " + ex.Message + ex.ToString()); //smd.GetType().Name
return null;
}
else
{
Console.WriteLine("Null value exception");
return null;
}
}
}
public static void Main()
{
SqlMetaData sqmd = new SqlMetaData("dt", SqlDbType.DateTime2, 27, 7);
SqlDataRecord sdr = new SqlDataRecord(sqmd);
sdr.SetValue(0, SQLTParser(sqmd, "2017-01-12 01:23:12.3456789"));
//set BreakPoint
//sdr -> Non-Public members -> _columnMetaData[0] -> Precision = 27
//sdr -> Non-Public members -> _columnSmiMetaData[0] -> Non-Public members -> Precision = 0
}
}
}
As noted, if you set the breakpoint and watches as indicated in MS Visual Studio*, Precision does not match between columnMetaData and columnSmiMetaData, which by the second such entry (!!) throws an exception:
Metadata for field 'dt' of record '2' did not match the original record's metadata.
which matches the exception thrown by
line 3755 of ValueUtilsSmi
due to the return of MetadataUtilsSmi.IsCompatible
Essentially, precision in the field's metadata of record 2 doesn't match that which is in the SmiMetaData of record 1. In record 1, the MD and SMD don't match either, but based on the logic Microsoft was using for an IEnumerator'd SqlDataRecord, it doesn't become an issue until the 2nd record.
Is this a MS bug? Or is there a way to force the precision value of the SmiMetaData? Or ignore that particular field check in ValueUtilsSmi? Specifying SqlMetaData sqmd = new SqlMetaData("dt", SqlDbType.DateTime2, 0, 7); allows the parsing to proceed, but drops sub-second precision from the data.
Here is, in a nutshell, how I'm attempting to send the data to a database. Apologies if this portion is not a complete example.
public class FullStreamingDataRecord : IEnumerable<SqlDataRecord>
{
private string _filePath;
public bool _hasHeader { get; private set; }
private ParserDict _pd; //notably has colStructure which is an array of SqlMetaData[]
public FullStreamingDataRecord(string FilePath, ParserDict pd)
{
_filePath = FilePath;
_pd = pd;
_hasHeader = true;
}
public static object SQLTParser(SqlMetaData smd, string val)
{
TypeCode systc = Parameter.ConvertDbTypeToTypeCode(smd.DbType);
try
{
return Convert.ChangeType(val, systc);
}
catch (Exception ex)
{
if (ex is InvalidCastException || ex is FormatException || ex is OverflowException)
{
Console.WriteLine("Exception reached casting " + val + " to " + Type.GetType("System."+Enum.GetName(typeof(TypeCode),systc)) + ": " + ex.Message + ex.ToString()); //smd.GetType().Name
return null; //smd.TParse(val);
}
else
{
Console.WriteLine("Null value exception casting...attempting a different method");
return null; smd.TParse(val);
}
}
}
public IEnumerator<SqlDataRecord> GetEnumerator()
{
int len = this._pd.colStructure.Length;
StreamReader fileReader = null;
try
{
using (fileReader = new StreamReader(this._filePath))
{
string inputRow = "";
string[] inputColumns = new string[len];
if (_hasHeader && !fileReader.EndOfStream)
{
inputRow = fileReader.ReadLine(); //and ignore
}
while (!fileReader.EndOfStream)
{
string temp = "";
inputRow = fileReader.ReadLine();
inputColumns = inputRow.Split(new char[]{','},len);
SqlDataRecord dataRecord = this._pd.colStructure
for (int j = 0; j < len; j++) { // i = counter for input columns
string currentKey = this._pd.colStructure[j].SqlMetaData.Name;
string curval = inputColumns[j];
var ty = this._pd.colStructure[j].SqlMetaData; //.DbType;
dataRecord.SetValue(j, SQLTParser(ty, curval));
// dataRecord.GetSqlMetaData(j).Adjust(dataRecord.GetValue(j));
}
yield return dataRecord;
}
}
}
// no catch block allowed due to the "yield" command
finally
{
fileReader.Close();
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
Which I call with this in my Main()
using (SqlConnection conn = new DBConnect().conn)
{
conn.Open();
SqlCommand importProc = new SqlCommand("tvp_"+pd.tableDestination, conn);
importProc.CommandType = CommandType.StoredProcedure;
importProc.CommandTimeout = 300;
SqlParameter importTable = new SqlParameter();
importTable.ParameterName = "#ImportTable";
importTable.TypeName = "dbo.tt_"+pd.tableDestination;
importTable.SqlDbType = SqlDbType.Structured;
importTable.Value = new FullStreamingDataRecord(fn, pd);
importProc.Parameters.Add(importTable);
importProc.ExecuteNonQuery(); //this line throws the exception
}
Apologies for not Console.WriteLineing the values of these watches.
Unfortunately, it seems that these parameters are protected against examination using Reflection's sdr.GetType().GetProperties(), even with the appropriate BindingFlags set. But at least you can see the values in debug mode!

Reading a file, reporting errors and inserting data into SQL Server database

The below code reads a texts file, formats it, displays any error and insert the data into SQL Server Database. I wrote the below code previously in Visual Basic, now I am trying to rewrite the code int C# but it is not working.
I cannot get the fields indicated to insert into a database: I am trying to get the records without errors to insert into the database even when their are error with other rows.
This was a project I did piece by piece as I am still learning this stuff, so please forgive my ignorance. The database portion seems fine so I did not post it but I can if requested.
Classes from file:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Configuration;
namespace ConsoleApplication1
{
class ClsMethods
{
public class MemberInfo
{
public static string MemberPhone;
public static string MemberName;
public static string MemberAddr1;
public static string MemberAddr2;
public static string MemberCity;
public static string MemberState;
public static string MemberZip;
}
public class ErrLog
{
public static int RowNum;
public static List<string> Err;
public ErrLog(int row)
{
RowNum = row;
Err = new List<string>();
}
public ErrLog()
{
Err = new List<string>();
}
}
}
}
MainCode:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Configuration;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
public static class MainModule
{
static List<ClsMethods.ErrLog> ErrList;
public static void Main()
{
string strFilename = null;
FileInfo fiFile = default(FileInfo);
StreamReader srData = default(StreamReader);
string strRecord = "";
List<ClsMethods.MemberInfo> MbrList = default(List<ClsMethods.MemberInfo>);
ClsMethods.MemberInfo MbrInfo = default(ClsMethods.MemberInfo);
int successCount = 0;
int failedCount = 0;
int totalCount = 0;
ErrList = new List<ClsMethods.ErrLog>();
strFilename = "C:\\EMP\\Member.csv";
fiFile = new FileInfo(strFilename);
if (fiFile.Exists)
{
if (fiFile.Length > 0)
{
MbrList = new List<ClsMethods.MemberInfo>();
srData = new StreamReader(strFilename);
while (srData.Peek() > 0)
{
try
{
strRecord = srData.ReadLine().Replace("\"", "");
totalCount = totalCount + 1;
String[] rec = strRecord.Split(",".ToCharArray());
if ((ValidateRow(rec, totalCount)))
{
MbrInfo = new ClsMethods.MemberInfo();
ClsMethods.MemberInfo.MemberPhone = rec[0];
ClsMethods.MemberInfo.MemberName = rec[1];
ClsMethods.MemberInfo.MemberAddr1 = rec[2];
ClsMethods.MemberInfo.MemberAddr2 = rec[3];
ClsMethods.MemberInfo.MemberCity = rec[4];
ClsMethods.MemberInfo.MemberState = rec[5];
ClsMethods.MemberInfo.MemberZip = rec[6];
MbrList.Add(MbrInfo);
}
}
catch (Exception ex)
{
Console.WriteLine("READ: " + ex.Message);
srData.Close();
srData.Dispose();
}
Console.WriteLine(strRecord);
}
foreach (ClsMethods.MemberInfo emp in MbrList)
{
if ((ClsDatabase.InsertMemberInfo(MbrInfo)))
{
successCount = successCount + 1;
}
else
{
failedCount = failedCount + 1;
}
}
Console.WriteLine("Total rows: {0} ", totalCount);
Console.WriteLine("Records without Errors: {0} ", MbrList.Count);
Console.WriteLine("Records with errors: {0} ", ErrList.Count);
Console.WriteLine("Inserted successfully: " + successCount.ToString());
Console.WriteLine("Failed: " + failedCount.ToString());
if ((ErrList.Count > 0))
{
Console.WriteLine("If you want to display errors press D. If you want to store errors in log file press F.");
ConsoleKeyInfo cki = default(ConsoleKeyInfo);
cki = Console.ReadKey();
Console.WriteLine();
string res = "";
res = cki.Key.ToString(res.ToUpper());
if ((res == "D"))
{
DisplayErrors();
}
else if ((res == "F"))
{
WriteErrorsToFile();
}
}
}
else
{
Console.WriteLine("File " + strFilename + " is empty");
}
}
else
{
Console.WriteLine("File " + strFilename + " doesn't exists");
}
Console.WriteLine("Program End. Press any key to exit");
Console.ReadKey();
Environment.Exit(0);
}
public static void DisplayErrors()
{
foreach (ClsMethods.ErrLog err in ErrList)
{
foreach (string errDescr in ClsMethods.ErrLog.Err)
{
Console.WriteLine("Line " + ClsMethods.ErrLog.RowNum.ToString() + ": " + errDescr);
}
}
}
public static void WriteErrorsToFile()
{
string path = "C:\\Log\\log.txt";
// Delete the file if it exists.
if (File.Exists(path))
{
File.Delete(path);
}
using (StreamWriter outfile = new StreamWriter(File.Create(path)))
{
foreach (ClsMethods.ErrLog err in ErrList)
{
foreach (string errDescr in ClsMethods.ErrLog.Err)
{
outfile.WriteLine("Line " + ClsMethods.ErrLog.RowNum.ToString() + ": " + errDescr);
}
}
}
}
public static bool ValidateRow(string[] rec, int rowIndex)
{
ClsMethods.ErrLog Err = new ClsMethods.ErrLog();
if ((rec.Length != 7))
{
ClsMethods.ErrLog.Err.Add("Wrong number of values in row");
}
else
{
rec[0] = rec[0].Replace("-", "");
if ((string.IsNullOrEmpty(rec[0])))
{
ClsMethods.ErrLog.Err.Add("Phone is empty");
}
if ((string.IsNullOrEmpty(rec[1])))
{
ClsMethods.ErrLog.Err.Add("Name is empty");
}
if ((string.IsNullOrEmpty(rec[2])))
{
ClsMethods.ErrLog.Err.Add("Address is empty");
}
if ((string.IsNullOrEmpty(rec[4])))
{
ClsMethods.ErrLog.Err.Add("City is empty");
}
if ((string.IsNullOrEmpty(rec[5])))
{
ClsMethods.ErrLog.Err.Add("State is empty");
}
if ((string.IsNullOrEmpty(rec[6])))
{
ClsMethods.ErrLog.Err.Add("Zip is empty");
}
}
if ((ClsMethods.ErrLog.Err.Count > 0))
{
ClsMethods.ErrLog.RowNum = rowIndex;
ErrList.Add(Err);
return false;
}
else
{
return true;
}
}
}
}
}
Database Connection and Parameters:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Configuration;
namespace ConsoleApplication1
{
class ClsDatabase
{
public static SqlConnection GetConnection()
{
SqlConnection InitCnt = null;
InitCnt = new SqlConnection();
InitCnt.ConnectionString = "Server=MyDB;database=Example;Trusted_Connection=true;";
try
{
InitCnt.Open();
}
catch (Exception ex)
{
InitCnt.Close();
InitCnt.Dispose();
}
return InitCnt;
}
public static bool InsertMemberInfo(ClsMethods.MemberInfo MbrInfo)
{
SqlConnection InitCnt = default(SqlConnection);
SqlCommand InitCmd = default(SqlCommand);
InitCnt = GetConnection();
if ((InitCnt != null))
{
InitCmd = new SqlCommand();
InitCmd.Connection = InitCnt;
InitCmd.CommandText = "uspInsertMemberInformation";
InitCmd.CommandType = CommandType.StoredProcedure;
InitCmd.Parameters.Add(new SqlParameter("#MemberPhone", SqlDbType.NVarChar, 10));
InitCmd.Parameters["#MemberPhone"].Direction = ParameterDirection.Input;
InitCmd.Parameters["#MemberPhone"].Value = ClsMethods.MemberInfo.MemberPhone;
InitCmd.Parameters.Add(new SqlParameter("#MemberName", SqlDbType.NVarChar, 50));
InitCmd.Parameters["#MemberName"].Value = ClsMethods.MemberInfo.MemberName;
InitCmd.Parameters["#MemberName"].Value = ClsMethods.MemberInfo.MemberName;
InitCmd.Parameters.Add(new SqlParameter("#MemberAddr1", SqlDbType.NVarChar, 30));
InitCmd.Parameters["#MemberAddr1"].Direction = ParameterDirection.Input;
InitCmd.Parameters["#MemberAddr1"].Value = ClsMethods.MemberInfo.MemberAddr1;
InitCmd.Parameters.Add(new SqlParameter("#MemberAddr2", SqlDbType.NVarChar, 30));
InitCmd.Parameters["#MemberAddr2"].Direction = ParameterDirection.Input;
InitCmd.Parameters["#MemberAddr2"].Value = ClsMethods.MemberInfo.MemberAddr2;
InitCmd.Parameters.Add(new SqlParameter("#MemberCity", SqlDbType.NVarChar, 20));
InitCmd.Parameters["#MemberCity"].Direction = ParameterDirection.Input;
InitCmd.Parameters["#MemberCity"].Value = ClsMethods.MemberInfo.MemberCity;
InitCmd.Parameters.Add(new SqlParameter("#MemberState", SqlDbType.NChar, 2));
InitCmd.Parameters["#MemberState"].Direction = ParameterDirection.Input;
InitCmd.Parameters["#MemberState"].Value = ClsMethods.MemberInfo.MemberState;
InitCmd.Parameters.Add(new SqlParameter("#MemberZip", SqlDbType.NVarChar, 9));
InitCmd.Parameters["#MemberZip"].Direction = ParameterDirection.Input;
InitCmd.Parameters["#MemberZip"].Value = ClsMethods.MemberInfo.MemberZip;
try
{
InitCmd.ExecuteNonQuery();
}
catch (Exception ex)
{
return false;
}
finally
{
InitCmd.Parameters.Clear();
InitCnt.Close();
}
}
return true;
}
}
}
Some really peculiar stuff there:
ClsMethods contains only classes and is not used; remove it.
MemberInfo contains only static fields, so every instance must always contain the same data.
ErrLog contains only a static field so, again, every instance will always contain the same data.
Main pointlessly sets a bunch of variables to default, which is always null, which is redundant. Why are you doing that?
MainModule is also redundant and should be removed.
All variables are global, which is unnecessary and risky.
MbrInfo = new ClsMethods.MemberInfo(); is useless because all fields are static, you will just be overwriting what is already there.
ClsDatabase.InsertMemberInfo(MbrInfo) will always pass the last record as many times as there are records in the file. I'm guessing you want ClsDatabase.InsertMemberInfo(emp). See why globals are bad?
InsertMemberInfo ignores the parameter you pass and uses the single static value for every parameter.
The default SqlParameter.Direction is Input, you don't have to reset it.
I wouldn't add "Member" to the front to every field; it's already in the class name. I'm guessing what you want is:
public class MemberInfo
{
public string Phone;
public string Name;
public string Addr1;
public string Addr2;
public string City;
public string State;
public string Zip;
}
Then in Main you can call:
MemberInfo mi = new MemberInfo();
mi.Phone = rec[0];
mi.Name = rec[1];
mi.Addr1 = rec[2];
mi.Addr2 = rec[3];
mi.City = rec[4];
mi.State = rec[5];
mi.Zip = rec[6];
MbrList.Add(mi);
You use the word Err to refer to a class, the log, and instance variables. This is very confusing. I suggest something like:
public class ErrLog
{
public int RowNum;
public List<string> Messages;
public ErrLog(int row)
: base()
{
RowNum = row;
}
public ErrLog()
{
Messages = new List<string>();
}
}
Your InsertMemberInfo should look more like this:
var sp = new SqlParameter("#MemberPhone", SqlDbType.NVarChar, 10);
sp.Value = MbrInfo.whatever;
InitCmd.Parameters.Add(sp);
Don't do this:
try
{
InitCmd.ExecuteNonQuery();
}
catch (Exception ex)
{
return false;
}
That will discard the reason the procedure failed. Just do this:
InitCmd.ExecuteNonQuery();
Exceptions. Use them. A few more weird things in your code; start with what I've shown.

This IfxTransaction has completed; it is no longer usable

Q:
When I use the transactions ,I'll get the following error on about 1 out of every 100 record.
This IfxTransaction has completed; it
is no longer usable
I can't expect when the error happen or what is the reason of this error.
I try to insert about 607 record in the same transaction.
My code:
public static int InsertGroups(List<Group> groups)
{
DBConnectionForInformix con = new DBConnectionForInformix("");
con.Open_Connection();
con.Begin_Transaction();
int affectedRow = -1;
Dictionary<string, string> groupsParameter = new Dictionary<string, string>();
try
{
foreach (Group a in groups)
{
groupsParameter.Add("id", a.GroupId.ToString());
groupsParameter.Add("name", a.Name);
groupsParameter.Add("studentcount", a.StudentCount.ToString());
groupsParameter.Add("divisiontag", a.DivisionTag.ToString());
groupsParameter.Add("entireclass", a.EntireClass.ToString());
groupsParameter.Add("classid", a.ClassId.ToString());
groupsParameter.Add("depcode", a.DepCode.ToString());
groupsParameter.Add("studycode", a.StudyCode.ToString());
groupsParameter.Add("batchnum", a.BatchNum.ToString());
affectedRow = DBUtilities.InsertEntityWithTrans("groups", groupsParameter, con);
groupsParameter.Clear();
if (affectedRow < 0)
{
break;
}
}
if (affectedRow > 0)
{
con.current_trans.Commit();
}
}
catch (Exception ee)
{
string message = ee.Message;
}
con.Close_Connection();
return affectedRow;
}
public void Begin_Transaction()
{
if (this.connection.State == ConnectionState.Open)
{
this.current_trans = this.connection.BeginTransaction(IsolationLevel.Serializable);
}
}
public static int InsertEntityWithTrans(string tblName, Dictionary<string, string> dtParams, DBConnectionForInformix current_conn)
{
int Result = -1;
string[] field_names = new string[dtParams.Count];
dtParams.Keys.CopyTo(field_names, 0);
string[] field_values = new string[dtParams.Count];
string[] field_valuesParam = new string[dtParams.Count];
dtParams.Values.CopyTo(field_values, 0);
for (int i = 0; i < field_names.Length; i++)
{
field_valuesParam[i] = "?";
}
//----------------------------------------------------------------------------------------------------------------------------------------------
string insertCmd = #"INSERT INTO " + tblName + " (" + string.Join(",", field_names) + ") values (" + string.Join(",", field_valuesParam) + ")";
//----------------------------------------------------------------------------------------------------------------------------------------------
IfxCommand com = new IfxCommand(insertCmd);
for (int j = 0; j < field_names.Length; j++)
{
com.Parameters.Add("?", field_values[j]);
}
try
{
Result = current_conn.Execute_NonQueryWithTransaction(com);
if (current_conn.connectionState == ConnectionState.Open && Result > 0)//OK: logging
{
# region // Log Area
#endregion
}
}
catch (Exception ex)
{
throw;
}
return Result;
}
public int Execute_NonQueryWithTransaction(IfxCommand com)
{
string return_msg = "";
int return_val = -1;
Open_Connection();
com.Connection = this.connection;
com.Transaction = current_trans;
try
{
return_val = com.ExecuteNonQuery();
}
catch (IfxException ifxEx)// Handle IBM.data.informix : mostly catched
{
return_val = ifxEx.Errors[0].NativeError;
return_msg = return_val.ToString();
}
catch (Exception ex)// Handle all other exceptions.
{
return_msg = ex.Message;
}
finally
{
if (!string.IsNullOrEmpty(return_msg))//catch error
{
//rollback
current_trans.Rollback();
Close_Connection();
connectionstate = ConnectionState.Closed;
}
}
return return_val;
}
You seem to be handling errors and rolling back the transaction in two places (in Execute_NonQueryWithTransaction and in InsertGroups.
And the return from Execute_NonQueryWithTransaction is used both to return error codes and to return rows affected. But in InsertGroups it is checked purely as a rows affected.
Could you have an error code from Execute_NonQueryWithTransaction (so transaction rolled back) being treated as success (rows inserted) in InsertGroups and the commit then fails?
Overall the code needs significant cleanup:
A catch block to only throw is pointless and just adds noise.
Just use exceptions for error handling, all normal returns should indicate success.

Categories