I have a subroutine. It comapares whether values are empty then doing something. For example, if they are empty, then warnings are raised.
The code works fine. But when value are not empty, the warnings are still pop out. Please help me to correct the logic.
Thanks.
private void btnNew_Click(object sender, EventArgs e)
{
try
{
if (txtbox1.Text.ToString().Trim() == string.Empty)
{
goto Msg1;
}
if (txtbox2.Text.ToString().Trim() == string.Empty)
{
goto Msg2;
}
DataRow dr = mydataSet.Tables[0].NewRow();
dr["Descript"] = txtbox1.Text;
dr["Abbr"] = txtbox2.Text;
dr["SortOrder"] = Convert.ToDecimal(numericOrder.Value);
if (SortOrders.Contains((decimal)dr["SortOrder"]))
{
goto Msg3;
}
mydataSet.Tables[0].Rows.Add(dr);
dgv.DataSource = mydataSet.Tables[0];
Msg1:
MessageBox.Show("Description is required.");
Msg2:
MessageBox.Show("Abbr is required.");
Msg3:
MessageBox.Show("Please select another one, this one is already used.");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
From the above code, you see. if txtbox1 has some value, the program still displays Msg1. I want to avoid it.
Because labels are just labels, and code after them is executed sequentially.
Why can't you do just this:
try
{
if (txtbox1.Text.ToString().Trim() == string.Empty)
{
MessageBox.Show("Description is required.");
return;
}
if (txtbox2.Text.ToString().Trim() == string.Empty)
{
MessageBox.Show("Abbr is required.");
return;
}
DataRow dr = mydataSet.Tables[0].NewRow();
dr["Descript"] = txtbox1.Text;
dr["Abbr"] = txtbox2.Text;
dr["SortOrder"] = Convert.ToDecimal(numericOrder.Value);
if (SortOrders.Contains((decimal)dr["SortOrder"]))
{
MessageBox.Show("Please select another one, this one is already used.");
return;
}
mydataSet.Tables[0].Rows.Add(dr);
dgv.DataSource = mydataSet.Tables[0];
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
It's so much more readable.
Restructure your code to avoid goto - it is a relic and not much use in a properly object oriented codebase.
Returning from the method, throwing exceptions or building an errors dictionary are all better options than using goto.
For example, you can have a List<string> errors which you add to when you get an error condition.
If it is empty, no errors were encountered, if it isn't, there were.
This is a good case were goto is the wrong way to go. Use something like this instead.
private void btnNew_Click(object sender, EventArgs e)
{
try
{
bool error = false;
if (txtbox1.Text.ToString().Trim() == string.Empty)
{
MessageBox.Show("Description is required.");
error = true;
}
if (txtbox2.Text.ToString().Trim() == string.Empty)
{
MessageBox.Show("Abbr is required.");
error = true;
}
if (SortOrders.Contains(Convert.ToDecimal(numericOrder.Value)
{
MessageBox.Show("Please select another one, this one is already used.");
error = true;
}
if(error)
return;
DataRow dr = mydataSet.Tables[0].NewRow();
dr["Descript"] = txtbox1.Text;
dr["Abbr"] = txtbox2.Text;
dr["SortOrder"] = Convert.ToDecimal(numericOrder.Value);
mydataSet.Tables[0].Rows.Add(dr);
dgv.DataSource = mydataSet.Tables[0];
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Edit
Just figured that my code didn't actually do the same as his first sample since it only displayed the first error no matter how many that occured. Updated my sample to accomodate for that.
I've always been taught to avoid goto like the plague, and it's something I've followed for years. I've never even considered it to be an option when writing code.
Thinking about it though, I did read an article a few years ago (which I can't find now) which said you could credibly use gotos only if you used it to jump down code, and not up: a rule that is stuck to here.
Check here for more info: Does anyone still use [goto] in C# and if so why?
There are better ways of using goto statement, for instacne using "return" (when used in the middle of a method), "break" and "continue". Have you ever used one of these?
private void btnNew_Click(object sender, EventArgs e)
{
try
{
var description = txtbox1.Text.Trim();
if (string.IsNullOrEmpty(description))
{
MessageBox.Show("Description is required.");
return;
}
var abbr = txtbox2.Text.Trim();
if (string.IsNullOrEmpty(abbr))
{
MessageBox.Show("Abbr is required.");
return;
}
var numericOrderValue = Convert.ToDecimal(numericOrder.Value);
if (SortOrders.Contains(numericOrderValue)
{
MessageBox.Show("Please select another one, this one is already used.");
return;
}
DataRow dr = mydataSet.Tables[0].NewRow();
dr["Descript"] = description;
dr["Abbr"] = abbr;
dr["SortOrder"] = numericOrderValue;
mydataSet.Tables[0].Rows.Add(dr);
dgv.DataSource = mydataSet.Tables[0];
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void btnNew_Click(object sender, EventArgs e)
{
try
{
if (txtbox1.Text.ToString().Trim() == string.Empty)
{
MessageBox.Show("Description is required.");
}
if (txtbox2.Text.ToString().Trim() == string.Empty)
{
MessageBox.Show("Abbr is required.");
}
DataRow dr = mydataSet.Tables[0].NewRow();
dr["Descript"] = txtbox1.Text;
dr["Abbr"] = txtbox2.Text;
dr["SortOrder"] = Convert.ToDecimal(numericOrder.Value);
if (SortOrders.Contains((decimal)dr["SortOrder"]))
{
MessageBox.Show("Please select another one, this one is already used.");
}
mydataSet.Tables[0].Rows.Add(dr);
dgv.DataSource = mydataSet.Tables[0];
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Try this. It works.
Related
IN WPF project, whenever I try to add selected Student in selected university and display it on assoiated table.
Here is image of my table -
https://i.stack.imgur.com/KUHuF.png
I encounter this problem, once I hit update assosiated button.
public System.Data.Linq.Table<Student> Students
{
get
{
return this.GetTable<Student>();
}
}
The above code is in "Dataclasses1.designer.cs" window.
However, upon restarting the program, selected student is sucessfully added to selected university.
Here is my code -
private void UpdateAssociatedStudent_Click(object sender, RoutedEventArgs e)
{
if(ListUniversity.SelectedItem != null || ListStudent.SelectedItem != null)
{
using (dataContext = new DataClasses1DataContext())
{
UniversityManager universityManager = new UniversityManager
{
UniFK = int.Parse(ListUniversity.SelectedValue.ToString()),
StdFK = int.Parse(ListStudent.SelectedValue.ToString())
};
dataContext.UniversityManagers.InsertOnSubmit(universityManager);
dataContext.SubmitChanges();
}
ShowAssociatedStudents();
Sucess.Text = "Student is sucessfully added to University";
}
}
Edit - Adding image for error
https://i.stack.imgur.com/ApPxd.png
I think that you may need to change this line of code:
if(ListUniversity.SelectedItem != null || ListStudent.SelectedItem != null)
to
if(ListUniversity.SelectedItem != null && ListStudent.SelectedItem != null)
I've solved this issue by running try/catch instead of using 'Using' statement. my edited code looks like this.
//Add selected student from selected university in associated student listbox
private void UpdateAssociatedStudent_Click(object sender, RoutedEventArgs e)
{
if(ListUniversity.SelectedItem != null && ListStudent.SelectedItem != null)
{
try
{
uniManager = new UniversityManager()
{
UniFK = Convert.ToInt32(ListUniversity.SelectedValue),
StdFK = Convert.ToInt32(ListStudent.SelectedValue)
//UniFK = int.Parse(ListUniversity.SelectedItem.ToString()),
//StdFK = int.Parse(ListStudent.SelectedItem.ToString())
};
dataContext.UniversityManagers.InsertOnSubmit(uniManager);
dataContext.SubmitChanges();
ShowAssociatedStudents();
}
catch (FileNotFoundException)
{
Console.WriteLine("File Not Found.");
}
catch (OutOfMemoryException)
{
Console.WriteLine("Out of Memory.");
}
catch (IOException)
{
Console.WriteLine("An I/O error has occured.");
}
}
else
{
Failed.Text = "Please select the missing items from either university or student.";
}
}
In my project I'm trying to write code that will be nice to understand.
I currently split my data access functions in a seperate class.
What I'm trying to achieve however, is to catch the errors back to my form. I am not getting this currently and I was wondering why.
In my form I have the following code:
private void btn_Save_ItemClick(object sender, ItemClickEventArgs e)
{
if (dal.updatePerson(ObjectAfterSaving))
{
MessageBox.Show("Updated!");
}
else
{
MessageBox.Show("error");
};
}
In my dal object (derived from the DataAccess_Person class), I have the following method:
public bool updatePerson(Person p)
{
conn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["Database"].ConnectionString);
SqlCommand command = new SqlCommand(#"UPDATE Person
SET PersonName = #PersonName
WHERE PersonID = #PersonID", conn);
command.Parameters.Add("#PersonName", SqlDbType.VarChar).Value = p.Name
{
try
{
if (conn.State == ConnectionState.Closed)
{
conn.Open();
}
int a = command.ExecuteNonQuery();
conn.Close();
if (a > 0)
{
return true;
}
else
{
return false;
}
}
catch (SqlException ex)
{
ex.ToString();
return false;
}
}
}
My question is: let's say if my method falls in the catch. Will my front end (form) show it (Sql Exception for example) ? Or will i just get 'error' ? And If I will just get error, how I can improve my code to show the Exception instead of error?
A simple way is to remove the try catch from your DAL and add it to the form. For example:
private void btn_Save_ItemClick(object sender, ItemClickEventArgs e)
{
var result = "Success";
try
{
dal.updatePerson(ObjectAfterSaving);
}
catch (SqlException sqlEx)
{
result = sqlEx.Message;
}
catch (Exception ex)
{
result = ex.Message;
}
MessageBox.Show(result);
}
Just note that there's a lot of ways you can do this. My preference is to not include DAL specific exception types in my UI. Instead I may return a custom result type that has an errorcode and message and let my UI display that or generate a custom message based on the error code.
You‘ll just get „error“ in case of a SqlException. All other exceptions will crash your program if you don‘t have a global exception handler. If you want to show the error message you could introduce an out variable for the error message:
bool successful = MyMethod(out string errorMessage)
if (!successful)
{
MessageBox.Show(errorMessage);
}
public bool MyMethod(out string errorMessage)
{
errorMessage = "";
try
{
// do some stuff
return true;
}
catch(Exception ex)
{
errorMessage = ex.Message;
return false;
}
}
In my program I have a text box and on text change a filter is applied to my RadGrid. However, on backspace the filter is not reapplied.
private void txt_search_TextChanged_1(object sender, EventArgs e)
{
try
{
CompositeFilterDescriptor searchFilter = new CompositeFilterDescriptor();
searchFilter.FilterDescriptors.Add(new FilterDescriptor("product", FilterOperator.Contains, txt_search.Text));
this.radGridView1.EnableFiltering = true;
this.radGridView1.MasterTemplate.Templates[0].EnableFiltering = true;
this.radGridView1.MasterTemplate.Templates[0].ShowFilteringRow = false;
this.radGridView1.MasterTemplate.ShowFilteringRow = false;
this.radGridView1.MasterTemplate.Templates[0].ShowTotals = true;
this.radGridView1.MasterTemplate.Templates[0].ShowFilterCellOperatorText = false;
if (txt_search.Text != "")
{
this.radGridView1.MasterTemplate.Templates[0].FilterDescriptors.Add(searchFilter);
}
foreach (GridViewRowInfo row in radGridView1.MasterTemplate.Rows)
{
if (row.ChildRows.Count == 0)
{
row.IsVisible = false;
}
else
{
row.IsVisible = true;
}
}
}
catch (Exception ex)
{
MessageBox.Show("Something went wrong searching the grid. Please try again and contact I.T. if this problem persists.", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
Is there another function which needs to be generated that is applied on backspace?
This code is taken from another program I have which is written in VB.net and converted. The filter works as it should in the VB version and is reapplied when text is removed etc.
Any help appreciated.
I'm currently trying to do a really simple function that updates a category using LINQ. However dbContext.SaveChanges() always returns 0 rows updated even when I hardcode the categoryId to update which is really frustrating. I've already tried many forms of debugging but fail to find the problem. If anyone can help me figure out my dumb mistake, it would be greatly appreciated!
Things I've tried,
- Trying to see if row with that category_Id exists, always returns 1 which is correct.
var count = (from c in dbContext.RecipeCategories
where c.Category_Id == categoryToEdit
select c).Count();
Removing myCategory instead of trying to update it, works as well. It seems like only the update does not work.
dbContext.RecipeCategories.Remove(myCateogry);
My DALayer for category functions
public bool EditCategory(int categoryToEdit, RecipeCategory newCategoryInfo)
{
RecipeXchangeDBContext dbContext = new RecipeXchangeDBContext();
RecipeCategory myCategory = new RecipeCategory();
bool status = false;
myCategory = (from c in dbContext.RecipeCategories
where c.Category_Id == categoryToEdit
select c).First();
myCategory.Category_Name = newCategoryInfo.Category_Name;
myCategory.Description = newCategoryInfo.Description;
myCategory.CatGroup_Id = newCategoryInfo.CatGroup_Id;
try
{
if (dbContext.SaveChanges() == 1)
status = true;
else
status = false;
}
catch (InvalidOperationException ex)
{
status = false;
}
return status;
}
My attempt to call the function, always goes to else block, dbContext.SaveChanges() returns 0 with no exceptions thrown.
protected void btnEditCategory_Click(object sender, EventArgs e)
{
if (Request.QueryString["categoryId"] != null)
{
CategoryDAL categoryDAL = new CategoryDAL();
RecipeCategory myCategory = new RecipeCategory();
try
{
addDiv.Attributes["class"] = "hidden";
editDiv.Attributes["class"] = "display";
int categoryToEdit = Convert.ToInt32(Request.QueryString["categoryId"]);
myCategory.Category_Name = tbEditCategoryName.Text;
myCategory.Description = tbEditCategoryDescription.Text;
myCategory.CatGroup_Id = Convert.ToInt32(ddlEditCategoryGroupList.SelectedValue);
try
{
bool editStatus = categoryDAL.EditCategory(categoryToEdit, myCategory);
if (editStatus)
{
HttpContext.Current.Session["editStatus"] = "Successful";
Response.Redirect("~/Admin/ManageCategories.aspx");
}
else
{
lblEditStatus.Text = "Unable to update category, please try again";
lblEditStatus.CssClass = "alert-danger";
}
}
catch (Exception ex)
{
lblEditStatus.Text = Convert.ToString(ex);
lblEditStatus.CssClass = "alert-danger";
}
}
catch (Exception ex)
{
updateStatus.Attributes["class"] = "alert alert-info alert-dismissable fade in";
updateStatus.Visible = true;
lblStatus.Text = "Invalid categoryId.";
}
}
else
{
updateStatus.Attributes["class"] = "alert alert-info alert-dismissable fade in";
updateStatus.Visible = true;
lblStatus.Text = "Nothing to update.";
}
}
Update ** Seems like this is what's causing the problem. If the values of the form are prepopulated it doesn't seem to allow me to update the object. If I comment out the part where it populates the form. The update function works normally. Can anyone help me figure out why prepopulating the form causes the update to fail?
protected void Page_Load(object sender, EventArgs e)
{
// Populate Edit Fields
if (Request.QueryString["categoryId"] != null)
{
CategoryDAL categoryDAL = new CategoryDAL();
RecipeCategory myCategory = new RecipeCategory();
try
{
addDiv.Attributes["class"] = "hidden";
editDiv.Attributes["class"] = "display";
int categoryToGet = Convert.ToInt32(Request.QueryString["categoryId"]);
myCategory = categoryDAL.GetCategory(categoryToGet);
tbEditCategoryName.Text = myCategory.Category_Name;
tbEditCategoryDescription.Text = myCategory.Description;
ddlEditCategoryGroupList.SelectedValue = Convert.ToString(myCategory.CatGroup_Id);
}
catch(Exception ex)
{
updateStatus.Attributes["class"] = "alert alert-info alert-dismissable fade in";
updateStatus.Visible = true;
lblStatus.Text = "Could not get Category Info, please try again.";
}
}
}
I have the code below which works fine when the Session state is InProc. However when the Session state is Sql Server, HandleCallback never gets called. How do I change the code so HandleCallBack gets called?
private void TAdata(object sender, EventArgs e)
{
if (((Form)sender).DialogResult == DialogResult.No)
{
return;
}
if (Changed)
{
MessageBox.Show(this.ParentForm, "Save Payroll Changes First", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
else
{
SqlConnection dbconnAS = new SqlConnection(strDBconnAS);
{
try
{
AsyncCallback callback = new AsyncCallback(HandleCallback);
using (SqlCommand SQLcmd = new SqlCommand("dbo.KronosTaData", dbconnAS))
{
SQLcmd.CommandType = CommandType.StoredProcedure;
dbconnAS.Open();
Changed = true;
SQLcmd.BeginExecuteNonQuery(callback, SQLcmd);
strResult = "";
ExportProgress.Visible = true;
ExportProgress.Value = 0;
ExportProgress.Maximum = 120;
ExportTimer.Start();
}
}
catch (Exception ex)
{
Changed = false;
strResult = ex.Message;
if (dbconnAS != null)
{
dbconnAS.Close();
}
}
}
}
}
private void HandleCallback(IAsyncResult result)
{
try
{
using (SqlCommand SQLcmd = (SqlCommand)result.AsyncState)
{
int rowCount = SQLcmd.EndExecuteNonQuery(result);
strResult = "OK";
SQLcmd.Connection.Close();
}
}
catch (Exception ex)
{
strResult = ex.Message;
}
}
private void ExportTimer_Tick(object sender, EventArgs e)
{
//Timer Exists on UI thread
if (strResult == "")
{
if (cmdKronos.Enabled) cmdKronos.Enabled = false;
if (ExportProgress.Value > ExportProgress.Maximum - 10) ExportProgress.Maximum += 10;
ExportProgress.Value += 1;
}
else if (strResult == "OK")
{
Changed = false;
cmdKronos.Enabled = true;
ExportProgress.Visible = false;
ExportTimer.Stop();
MessageBox.Show(ParentForm, "Kronos data succesfully imported", "Data Import", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
Changed = false;
cmdKronos.Enabled = true;
ExportProgress.Visible = false;
ExportTimer.Stop();
MessageBox.Show(ParentForm, Text, "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
You are disposing the command as soon as you've finished starting it:
using (SqlCommand SQLcmd = new SqlCommand("dbo.KronosTaData", dbconnAS))
{
//...
SQLcmd.BeginExecuteNonQuery(callback, SQLcmd);
//...
}
that will abort everything - so indeed: it will never complete. Basically; using doesn't play nicely with Begin*/End*, so don't do that. You might find it much easier to do this using async/await, by the way (via ExecuteNonQueryAsync).
You also probably want to close and dispose the connection somewhere; again, async/await would make this much easier to get right.
The solution is to declare the variable strResult as static.
See Visual Webgui Variable Scope