My code checks for changes in the database and then sends an update via a web service to the client.
I had the part sending the message to the client working fine because making the calls to check for changes in the database. Now that I have added the portion checking database changes I am getting the following error.
When Debugging my code the error points at the exception at the very bottom of the code so I have no idea where the error is coming from and no way of fixing it.
Any advise would be greatly appreciated
SendInvUpdate.InvServices.UpdateRatePackagesRequest ur = new SendInvUpdate.InvServices.UpdateRatePackagesRequest();
SendInvUpdate.InvServices.UpdateRatePackagesOperationResponse or = new SendInvUpdate.InvServices.UpdateRatePackagesOperationResponse();
protected void Page_Load(object sender, EventArgs e)
{
try
{
string connStr = ConfigurationManager.ConnectionStrings["bb"].ConnectionString;
SqlConnection Con = new SqlConnection(connStr);
Con.Open();
SqlCommand cmd = new SqlCommand("invpush_PollForAvailableChanges", Con);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter NewSysChangeVersionParam = new SqlParameter("#NewSysChangeVersion", SqlDbType.Int);
NewSysChangeVersionParam.Value = (object)NewSysChangeVersionParam ?? DBNull.Value;
NewSysChangeVersionParam.Direction = ParameterDirection.InputOutput;
NewSysChangeVersionParam.SqlDbType = SqlDbType.BigInt;
SqlDataReader sdr = cmd.ExecuteReader();
InventoryPushSubscriptionRecord rec = new InventoryPushSubscriptionRecord();
while (sdr.Read())
{
rec.InventoryPushSubId = sdr.GetInt32(0);
rec.CMName = sdr.GetString(1);
rec.NotifUrl = sdr.GetString(2);
rec.Options = sdr.GetString(3);
rec.LastSysChangeVersion = sdr.IsDBNull(4)?(long?)null:sdr.GetInt32(4);
}
if(!sdr.NextResult()) throw new System.Exception("Expected Result set 1 for InventoryChangeRecord");
InventoryChangeRecord inrec = new InventoryChangeRecord();
while (sdr.Read())
{
inrec.InventoryPushSubId= sdr.GetInt32(0);
inrec.SysChangeVersion=sdr.IsDBNull(1)?(long?)null:sdr.GetInt32(1);
inrec.InvDate=sdr.GetDateTime(2);
inrec.ResId=sdr.GetInt32(3);
inrec.RoomType=sdr.GetString(4);
inrec.InvCount=sdr.GetInt32(5);
inrec.ResName=sdr.GetString(6);
}
sdr.Close();
sdr.Dispose();
if (NewSysChangeVersionParam != null)
{
int ResId;
Int64 ResoId;
ResortId = inrec.ResId;
SqlDataAdapter sda = new SqlDataAdapter("Select BID,RId from BBTest.bbtest.tblResMapping where BId=#ResId",Con);
SqlParameter resId = new SqlParameter("#ResId", ResId);
sda.SelectCommand.Parameters.Add(resId);
DataSet ds = new DataSet();
sda.Fill(ds, "tblresmapping");
if (ds.Tables[0].Rows.Count > 0)
{
ResoId = Convert.ToInt32(ds.Tables[0].Rows[0]["ResonlineId"]);
}
if (ds.Tables[0].Rows.Count != 0)
{
Int64 RatePackageId;
SqlDataAdapter sqlda = new SqlDataAdapter("Select BId,BBRoom,ResRatePackageID from tblResRatePackages where BID =#ResortId", Con);
SqlParameter resI = new SqlParameter("#RId", resId);
sqlda.SelectCommand.Parameters.Add(resI);
DataSet dt = new DataSet();
sqlda.Fill(dt, "tblResRatePackages");
if (dt.Tables[0].Rows.Count > 0)
{
RatePackageId = Convert.ToInt64(dt.Tables[0].Rows[0]["ResRatePackageID"]);
Int64 HID = ResId;
Int64 HRID = RatePackageId;
SendInvUpdate.InvServices.UpdateRatePackagesRequest request = new SendInvUpdate.InvServices.UpdateRatePackagesRequest();
request.HotelId = account.HotelId;
int avail = inrec.InvCount;
DateTime frodte = inrec.InvDate;
int NoofRatePackages = 3;
UpdateRatePackageRequest[] RatePackages = new UpdateRatePackageRequest[NoofRatePackages];
string res;
request.RatePackages = new UpdateRatePackageRequest[NoofRatePackages];
request.RatePackages = RatePackages;
for (int i = 0; i < NoofRatePackages; i++)
{
UpdateRatePackageRequest rp = new UpdateRatePackageRequest();
request.RatePackages[i] = rp;
rp.RatePackageId = HRID;
rp.Rates = new RateDetails[NoofRatePackages];
for (int j = 0; j < NoofRatePackages; j++)
{
RateDetails rd = new RateDetails();
rp.Rates[j] = rd;
rd.Availability = avail;
rd.AvailabilityApplicationType = SendInvUpdate.InvServices.AvailabilityApplicationType.SET;
rd.FromDate = frodte;
// rd.ToDate = todte;
}
}
SendInvUpdate.InvServices.InventoryServiceClient isc = new SendInvUpdate.InvServices.InventoryServiceClient();
or = isc.UpdateRatePackages(request);
res = or.Results.ToString();
}
}
}
}
catch (Exception ex)
{
throw (ex);
}
}
}
}
You're hiding your real exception stack trace by catching the exception and throwing it again like you're doing;
try {
...
}
catch(Exception ex) // catch all exceptions
{
throw ex; // throw the same exception, removing the old stack trace
}
Either you should just remove the whole try/catch, or change to;
try {
...
}
catch(Exception ex) // catch all exceptions
{
throw; // throw the last caught exception, keeping the stack trace
}
and you will suddenly be able to see the exact location of your original exception. I'm sure you will find your error right away.
In my case, getting this error message, Oracle turned out to be returning an irrational number.
My code was throwing the "Specified cast is not valid" exception at adapter.Fill(ds);.NET was not interpreting the returned number correctly with the code I had been using. The addition of the line adapter.ReturnProviderSpecificTypes = true; Made it possible for .NET to interpret the number, rounded to the Nth decimal (last digit rounded up from 3 to 4 for some reason...): 2.25000000000000333333333333333333333334
private static DataSet dataset_test(string sql)
{
DataSet ds = new DataSet();
using (OracleConnection objConn = new OracleConnection(connectionstring))
{
OracleCommand objCmd = new OracleCommand();
objCmd.Connection = objConn;
objCmd.CommandText = sql;
objCmd.CommandType = CommandType.Text;
try
{
objConn.Open();
OracleDataAdapter adapter = new OracleDataAdapter(objCmd);
adapter.ReturnProviderSpecificTypes = true;
adapter.Fill(ds);
}
catch (Exception)
{
throw;
}
objConn.Close();
return ds;
}
}
One thing to try: Set a breakpoint right at the start of the try-catch block, on the connStr = line, and step through the code line by line, progressing over method calls. In this way you can quickly track down which part of the code is throwing the error, and then home in on that point to look for the specific problem. (You will also be able to read the original exception and innerexception messages prior to the rethrow.)
Given the title of your question, so the assumption that the error you are having is a casting exception, the first place I would check would be in your database data retrieval code. You are using sdr.GetInt32(0) for instance, this would throw that sort of error if column 0 couldn't be converted to an integer.
Hope this helps. If you are able to track down more information, post it and we'll see if we can give more specific advice.
Related
I'm currently programming a bot for Twitch, where we want to store settings in a database.
The database itself is pre-created, so all columns which are requested, are there.
Somehow, when using the reader object, it immediately throws an IndexOutOfRangeException. I don't know what causes this error.
public static void GetConfigFromDb()
{
try
{
SQLiteConnection conn = new SQLiteConnection("Data Source=OakSettings.sqlite;");
conn.Open();
string sql = "SELECT * FROM oak_settings";
SQLiteCommand command = new SQLiteCommand(sql, conn);
SQLiteDataReader reader = command.ExecuteReader();
while (reader.Read())
{
//StreamerOAuthKey = (string)reader["StreamerOAuthToken"];
//BotOAuthKey = (string)reader["BotOAuthToken"];
//StreamerUsername = (string)reader["StreamerTwitchUsername"];
//BotUsername = (string)reader["BotTwitchUsername"];
StreamerOAuthKey = reader.GetString(reader.GetOrdinal("StreamerOAuthToken"));
BotOAuthKey = reader.GetString(reader.GetOrdinal("BotOAuthToken"));
StreamerUsername = reader.GetString(reader.GetOrdinal("StreamerTwitchUsername"));
BotUsername = reader.GetString(reader.GetOrdinal("BotTwitchUsername"));
}
conn.Close();
}
catch (Exception ex)
{
System.Windows.MessageBox.Show(ex.ToString());
}
}
The only occasion when this method gets called, is on startup of the application. The part which is commented, was the way I did it before, but then I changed it, in hope this was causing the error.
What causes the error?
I ran into a problem where passing a connection from a TableAdapter to some methods throws an exception stating the connectionstring isn't initialized. There are quite a few questions on SO with this exception but none were passing the connection and most were because the ConnectionString was null. Weird thing is I used MessageBox.Show(connection.ConnectionString); through out the chain of methods and I receive a valid connection string at every step. This is a somewhat complicated program that is in production but I will try to simplify the code for this question...
This is the postInventoryData method, which takes a DataGridView with inventory items and iterates through it posting them to the inventory. I use a TransactionScope to ensure the changes are safely rolled back in the event of an error. If an item is a kit(an item comprised of other items) I must iterate through those items and remove them from the inventory. The problem occurs when I check whether or not the item is a kit.
public bool postInventoryData(DataGridView dgv)
{
bool successful = true;
TestDataSetTableAdapters.inentoryTrxTableAdapter inventoryTrxAdapter =
new TestDataSetTableAdapters.inentoryTrxTableAdapter();
try
{
using (TransactionScope trxScope = new TransactionScope
(TransactionScopeOption.Required, new System.TimeSpan(0, 15, 0)))
{
MessageBox.Show(inventoryTrxAdapter.Connection.ConnectionString); // <-- Valid ConnectionString
inventoryTrxAdapter.OpenConnection();
for (int i = 0; i < dgv.Rows.Count; i++)
{
//parameter values
string departmentCode = dgv.Rows[i].Cells["Department_Code"].Value.ToString();
string machineCode = dgv.Rows[i].Cells["Machine_Code"].Value.ToString();
string operatorCode = dgv.Rows[i].Cells["Operator_Code"].Value.ToString();
string itemNumber = dgv.Rows[i].Cells["Item_Number"].Value.ToString();
double? qtyProduced = Convert.ToDouble(dgv.Rows[i].Cells["Quantity"].Value.ToString());
bool isKit =
businessLayer.isItemNumberKit
(inventoryTrxAdapter.Connection, itemNumber); // <-- CULPRIT!
// Inserts the item
dailyProductionInsertQty(
departmentCode,
machineCode,
operatorCode,
itemNumber,
isKit,
qtyProduced,
inventoryTrxAdapter,
trxScope);
}
inventoryTrxAdapter.CloseConnection();
trxScope.Complete();
}
}
catch (System.Exception ex)
{
successful = false;
MessageBox.Show(ex.ToString());
}
return successful;
}
The isItemNumberKit method
public bool isItemNumberKit(SqlConnection connection, string itemNumber)
{
bool contains;
MessageBox.Show(connection.ConnectionString); // <-- Valid ConnectionString
DataTable dt = getKit(connection, itemNumber); // <-- CULPRIT!
if (dt.Rows.Count > 0)
{
contains = true;
}
else
{
contains = false;
}
return contains;
}
The getKit method
public DataTable getKit(SqlConnection connection, string itemNumber)
{
DataTable dt = new DataTable();
SqlConnection myConnection = connection;
MessageBox.Show(myConnection.ConnectionString); // <-- Valid ConnectionString
SqlParameter paramItemNumber = new SqlParameter();
paramItemNumber.ParameterName = "#ItemNumber";
paramItemNumber.Value = itemNumber;
paramItemNumber.SqlDbType = System.Data.SqlDbType.VarChar;
try
{
using (myConnection)
{
string sql =
#"SELECT kits.Row_Id,
kits.Kit_Item_Number,
kits.Location_Code
FROM Inventory.dbo.Z_PV_Kits kits
WHERE kits.Kit_Item_Number=#ItemNumber";
//myConnection.Open();
using (SqlCommand myCommand = new SqlCommand(sql, myConnection))
{
myCommand.Parameters.Add(paramItemNumber);
SqlDataReader reader = myCommand.ExecuteReader();
dt.Load(reader);
}
}
}
catch (Exception ex)
{
dt = null;
MessageBox.Show(ex.ToString());
}
return dt;
}
When I execute postInventoryData the program throws an exception with the message, "The connectionstring property has not been initialized." with the line numbers pointing to isItemNumberKit and getKit. As you can see in the code above, I used a MessageBox.Show(connection.ConnectionString) throughout the process and each time I received a valid Connection string. I have created a workaround which stores a cached DataTable containing all the kit items I can run linq statements on. I am not in emergency mode or anything but I thought this to be weird and an opportunity for me to learn. Thanks in advance for any help!
It might be possible that you have 2 app.config files in your solution with 2 different connection strings.
OK, I figured it out and now when I think about it the answer was somewhat obvious. I always use using(){} blocks to ensure connections and similar objects are properly disposed and taken care of after they are used. The solution was to simply remove the using(myConnection){} block from the getKit method like this:
public DataTable getKit(SqlConnection connection, string itemNumber)
{
DataTable dt = new DataTable();
SqlConnection myConnection = connection;
MessageBox.Show(myConnection.ConnectionString);
SqlParameter paramItemNumber = new SqlParameter();
paramItemNumber.ParameterName = "#ItemNumber";
paramItemNumber.Value = itemNumber;
paramItemNumber.SqlDbType = System.Data.SqlDbType.VarChar;
try
{
string sql =
#"SELECT kits.Row_Id,
kits.Kit_Item_Number,
kits.Location_Code
FROM Inventory.dbo.Z_PV_Kits kits
WHERE kits.Kit_Item_Number=#ItemNumber
";
//myConnection.Open();
using (SqlCommand myCommand = new SqlCommand(sql, myConnection))
{
myCommand.Parameters.Add(paramItemNumber);
SqlDataReader reader = myCommand.ExecuteReader();
dt.Load(reader);
}
}
catch (Exception ex)
{
dt = null;
MessageBox.Show(ex.ToString());
}
return dt;
}
This will leave the connection intact but properly dispose of the command. Sorry for the long winded question with a short simple answer. Hope this might help someone someday.
With the following code I get a less-than-helpful err msg (all I can see of the err msg in the truncated title bar of the exception dialog is, "System.Data.SQLServer...")
string query = "SELECT * FROM EVERYTHING";
SqlCeCommand cmd = new SqlCeCommand(query);
SqlCeConnection conn = new SqlCeConnection(myConnStr);
conn.Open();
cmd.Connection = conn;
SqlCeDataReader myReader = cmd.ExecuteReader(CommandBehavior.CloseConnection); // <-- Blows up bigger than an Augustus Gloop pinata
UPDATE
I added this:
MessageBox.Show(string.Format("query is {0}", query));
...to do a sanity check on just what the query that was failing was, to the end that clumps of hair are now scattered all about my work area. I had this to feed the query:
string vendorId = txtVendor.ToString().Trim();
...instead of this:
string vendorId = txtVendor.Text.ToString().Trim();
...and thus the query was "SELECT BLA FROM BLA WHERE BLA = System.Windows.Forms.Label"
Now I'm at least to a "No data exists for the row/column" err msg.
I'm not sure if CF supports the CommandBehavior.CloseConnection option.
Can you write it this way?
string query = "SELECT * FROM EVERYTHING";
var table = new DataTable();
using (var cmd = new SqlCeCommand(query, new SqlCeConnection(myConnStr)); {
try {
cmd.Connection.Open();
table.Load(cmd.ExecuteReader());
} catch (SqlException err) {
Console.WriteLine(err.Message); // <= Put a Break Point here.
} finally {
cmd.Connection.Close();
}
}
object col1 = null;
string strCol2 = null;
if (0 < table.Rows.Count) {
col1 = table.Rows[0][0];
object obj = table.Rows[0][1];
if ((obj != null) && (obj != DBNull.Value)) {
strCol2 = obj.ToString();
}
}
EDIT: Added DataTable and read 2 items from Row[0].
Sorry for the noobiness here but I'm having an issue with the following SQL connection in C# asp.net
#region Get Employee Logins
DataSet ds_Logins;
SqlDataAdapter da_Logins;
SqlCommand cmdLogins = new SqlCommand("IFACE_SB_EMPLOYEE", SBConn.sbConn);
cmdLogins.Parameters.Add("#Statement", SqlDbType.Char).Value = "GetLogins";
cmdLogins.Parameters.Add("#i_FK_EmployeeID", SqlDbType.Char).Value = Request["i_FK_EmployeeID"].Trim().ToString();
cmdLogins.CommandType = CommandType.StoredProcedure;
da_Logins = new SqlDataAdapter(cmdLogins);
try
{
SBConn.sbConn.Open();
da_Logins = new DataSet();
int row = da_Logins.Fill(ds_Logins, "SB_SST_EXCHANGERATE");
if (row <= 0)
{
}
else
{
GridViewSystemsLogin.DataSource = ds_Logins.Tables[0];
GridViewSystemsLogin.DataBind();
}
SBConn.sbConn.Close();
}
catch (Exception )
{
}
#endregion
Can anybody help me with what the pickle is wrong we it seeing as its been copied from an existing working file and re-jigged in the stored procedure and table aspects.
Thanks
Marcus
This line
da_Logins = new DataSet();
should read
ds_Logins = new DataSet();
This one has me stumped. Here are the relative bits of code:
public AgencyDetails(Guid AgencyId)
{
try
{
evgStoredProcedure Procedure = new evgStoredProcedure();
Hashtable commandParameters = new Hashtable();
commandParameters.Add("#AgencyId", AgencyId);
SqlDataReader AppReader = Procedure.ExecuteReaderProcedure("evg_getAgencyDetails", commandParameters);
commandParameters.Clear();
//The following line is where the error is thrown. Errormessage: Invalid attempt to call Read when reader is closed.
while (AppReader.Read())
{
AgencyName = AppReader.GetOrdinal("AgencyName").ToString();
AgencyAddress = AppReader.GetOrdinal("AgencyAddress").ToString();
AgencyCity = AppReader.GetOrdinal("AgencyCity").ToString();
AgencyState = AppReader.GetOrdinal("AgencyState").ToString();
AgencyZip = AppReader.GetOrdinal("AgencyZip").ToString();
AgencyPhone = AppReader.GetOrdinal("AgencyPhone").ToString();
AgencyFax = AppReader.GetOrdinal("AgencyFax").ToString();
}
AppReader.Close();
AppReader.Dispose();
}
catch (Exception ex)
{
throw new Exception("AgencyDetails Constructor: " + ex.Message.ToString());
}
}
And the implementation of ExecuteReaderProcedure:
public SqlDataReader ExecuteReaderProcedure(string ProcedureName, Hashtable Parameters)
{
SqlDataReader returnReader;
using (SqlConnection conn = new SqlConnection(connectionString))
{
try
{
SqlCommand cmd = new SqlCommand(ProcedureName, conn);
SqlParameter param = new SqlParameter();
cmd.CommandType = System.Data.CommandType.StoredProcedure;
foreach (DictionaryEntry keyValue in Parameters)
{
cmd.Parameters.AddWithValue(keyValue.Key.ToString(), keyValue.Value);
}
conn.Open();
returnReader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
}
catch (SqlException e)
{
throw new Exception(e.Message.ToString());
}
}
return returnReader;
}
The connection string is working as other stored procedures in the same class run fine. The only problem seems to be when returning SqlDataReaders from this method! They throw the error message in the title. Any ideas are greatly appreciated! Thanks in advance!
A DataReader is generally connected directly to the database. In this case, when you return from the method, you're returning from inside the using statement that created the SqlConnetion object. That will call Dispose on the SqlConnection, and render the SqlDataReader useless.
Try this:
public SqlDataReader ExecuteReaderProcedure(string ProcedureName, Hashtable Parameters)
{
SqlConnection conn = new SqlConnection(connectionString);
using(SqlCommand cmd = new SqlCommand(ProcedureName, conn))
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
foreach(DictionaryEntry keyValue in Parameters)
{
cmd.Parameters.AddWithValue(keyValue.Key.ToString(), keyValue.Value);
}
conn.Open();
return cmd.ExecuteReader(CommandBehavior.CloseConnection);
}
}
Call it like this:
public AgencyDetails(Guid AgencyId)
{
evgStoredProcedure Procedure = new evgStoredProcedure();
Hashtable commandParameters = new Hashtable();
commandParameters.Add("#AgencyId", AgencyId);
using(SqlDataReader AppReader =
Procedure.ExecuteReaderProcedure("evg_getAgencyDetails",
commandParameters))
{
commandParameters.Clear();
while(AppReader.Read())
{
AgencyName = AppReader.GetOrdinal("AgencyName").ToString();
AgencyAddress = AppReader.GetOrdinal("AgencyAddress").ToString();
AgencyCity = AppReader.GetOrdinal("AgencyCity").ToString();
AgencyState = AppReader.GetOrdinal("AgencyState").ToString();
AgencyZip = AppReader.GetOrdinal("AgencyZip").ToString();
AgencyPhone = AppReader.GetOrdinal("AgencyPhone").ToString();
AgencyFax = AppReader.GetOrdinal("AgencyFax").ToString();
}
}
}
At the end of the using statement for AppReader, AppReader.Dispose will be called. Since you called ExecuteReader with CommandBehavior.CloseConnection, Disposing of the reader will also close the connection.
Note that I got rid of your bad exception handling as well. Never use ex.Message except possibly for displaying to end-users. Everyone else will want the full exception. Also, no need to print the method name as part of the exception message if you're allowing the full exception to propagate. The method name will be in the stack trace.