I am building a C# WinUI 3 desktop app running on Windows 10. I want to use a contentdialog to display error messages.
I am calling this method from multiple catch clauses:
private async void DisplayErrorDialog(string content)
{
ContentDialog ErrorDialog = new ContentDialog()
{
Title = "* Error *",
Content = content,
CloseButtonText = "Ok"
};
// XamlRoot must be set in the case of a ContentDialog running in a Desktop app
ErrorDialog.XamlRoot = this.Content.XamlRoot;
ContentDialogResult result = await ErrorDialog.ShowAsync();
}
Here is how I call the method:
catch (SqlException Sql_Error)
{
Debug.WriteLine($"Hello SQL error GetSQLData_App_View_Results_2020: {Sql_Error.Message}");
DisplayErrorDialog($"GetSQLData_App_View_Results_2020 (SQL Error): {Sql_Error.Message}");
}
catch (Exception Other_Error)
{
Debug.WriteLine($"Hello Other error GetSQLData_App_View_Results_2020: {Other_Error.Message}");
DisplayErrorDialog($"GetSQLData_App_View_Results_2020 (Other Error): {Other_Error.Message}");
}
}
I have many other contentdialogs working successfully within my application. I wanted/needed to test this error contentdialog so I explicitly threw an exception this way:
throw new Exception("SQL test exception #1");
The throw does work and the catch clause 'catches' the exception. However I am getting this error in the contentdialog:
Exception thrown at 0x00007FFFD5FE3FA9 (KernelBase.dll) in MetricReporting.exe: WinRT originate error - 0x80070057 : 'This element is already associated with a XamlRoot, it cannot be associated with a different one until it is removed from the previous XamlRoot.'.
I cannot figure this out. I am a beginner C# and WinUI 3 developer. Thank you for your help and guidance.
Thank you Andrew for your observation.
Here is more of my code:
public pageResults()
{
this.InitializeComponent();
Debug.WriteLine($"### --- InitializeComponents() Completed --- ###");
FetchSQLData_Ref_Metric();
FetchSQLData_Ref_Metric_MarketID();
FetchSQLData_StateCodes();
FetchSQLData_MetricYear();
FetchSQLData_Results();
Display_Results();
}
I am doing a lot of sql fetching of data into datatables and then I display the datatable in a datagrid on the page, which is part of a navigationview.
I inserted the 'throw' inside of a method that is inside of 'FetchSQLData_Results()'
private void FetchSQLData_Results()
{
string metricYear = string.Empty;
// Pre-load all views into their own separate datatables. Each views represents a metric year.
// At this time there are views for 2020, 2021, and 2022
foreach (DataRow row in dtMetricYear.Rows)
{
metricYear = row["metricyear"].ToString();
GetSQLData_App_View_Results_(metricYear);
}
}
private void GetSQLData_App_View_Results_(string metricYear)
{
// Load datatables with existing views
switch (metricYear)
{
case "2020":
GetSQLData_App_View_Results_2020();
break;
case "2021":
GetSQLData_App_View_Results_2021();
break;
case "2022":
GetSQLData_App_View_Results_2022();
break;
case "2023":
break;
case "2024":
break;
default:
break;
}
}
The throw is here:
public void GetSQLData_App_View_Results_2020()
{
try
{
using (SqlConnection con = new SqlConnection("Data Source = xxxx; Initial Catalog = xxxx; Integrated Security = True; Connect Timeout = 15; Encrypt = False; TrustServerCertificate = True; ApplicationIntent = ReadWrite; MultiSubnetFailover = False"))
{
**//throw new Exception("SQL test exception #1");**
//Prepare sql
//string sql = "select * from dbo.app_emb_prd_lvl_results_2020 order by metric_id";
string sql = "select * from app_emb_prd_lvl_results_2020 v join dbo.Ref_Metric r on v.metric_id = r.Metric_ID order by v.metric_id";
SqlCommand cmd = new SqlCommand(sql, con);
cmd.CommandType = System.Data.CommandType.Text;
//Open the connection
con.Open();
// Create adapter and fill the datatable with returned data from sql command
using (SqlDataAdapter adap = new SqlDataAdapter(cmd))
{
dtResults2020.Clear();
adap.Fill(dtResults2020);
try
{.. intentionally left blank ..}
catch (Exception List_Error)
{
Debug.WriteLine($"List error GetSQLData_App_View_Results_2020: {List_Error.Message}");
}
Debug.WriteLine($"GetSQLData_App_View_Results_2020 Completed");
} // end using sql adapter
} // end using sql connection
}
catch (SqlException Sql_Error)
{
Debug.WriteLine($"Hello SQL error GetSQLData_App_View_Results_2020: {Sql_Error.Message}");
DisplayErrorDialog($"GetSQLData_App_View_Results_2020 (SQL Error): {Sql_Error.Message}");
}
catch (Exception Other_Error)
{
Debug.WriteLine($"Hello Other error GetSQLData_App_View_Results_2020: {Other_Error.Message}");
DisplayErrorDialog($"GetSQLData_App_View_Results_2020 (Other Error): {Other_Error.Message}");
}
}
As I mentioned in the comments, XamlRoad might not be ready. Try fetching your data in Loaded instead of the constructor.
public pageResults()
{
this.InitializeComponent();
this.Loaded += pageResults_Loaded;
Debug.WriteLine($"### --- InitializeComponents() Completed --- ###");
}
private void pageResults_Loaded(object sender, RoutedEventArgs e)
{
FetchSQLData_Ref_Metric();
FetchSQLData_Ref_Metric_MarketID();
FetchSQLData_StateCodes();
FetchSQLData_MetricYear();
FetchSQLData_Results();
Display_Results();
}
Related
My C# program works with a MySQL database.
For some reason the program cannot catch exceptions caused my the MySQL connection.
Example:
If I make the credentials in the connection string invalid, the program crashes like this (even when running in the debugger): http://imgur.com/SfzkVdW
The connection code is like this:
using MySQLDriverCS;
namespace XXX
{
public class Data
{
private static MySQLConnection con;
static Data()
{
string connectionString = new MySQLConnectionString("XXX",
"XXX",
"XXX",
"XXX").AsString;
con = new MySQLConnection(connectionString + ";CharSet=utf8");
con.Open(); // For testing the connection
con.Close();
}
...
Any ideas for how I can improve things and start catching MySQL exceptions?
I have tried wrapping the code in the static constructor in a try-catch. That didn't help. The program still crashed in the same way.
Thanks.
Same code with the try-catch wrapper. It still fails with the same error: http://imgur.com/SfzkVdW
static Data()
{
try
{
string connectionString = new MySQLConnectionString("XXX",
"XXX",
"XXX",
"XXX").AsString;
con = new MySQLConnection(connectionString + ";CharSet=utf8");
con.Open(); // For testing the connection
con.Close();
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Use the appropriate exception type in the catch block.
Use the appropriate MySQL classes.
using MySql.Data.MySqlClient;
// class level var or whatnot:
string connString = #"server=theHostName;userid=dbuser123;password=OpenSesame7;database=my_db_name";
public void connect()
{
try
{
conn = new MySqlConnection(connString); // read above comments for (conn)
conn.Open();
}
catch (MySqlException ex)
{
MessageBoxButtons buttons = MessageBoxButtons.OK;
string s="MySqlException: "+ex.ToString();
MessageBox.Show(s,"Error",buttons);
}
finally
{
if (conn != null)
{
//conn.Close();
}
}
}
Error Caught No Problem:
Add References screenshot:
Catching or handling exceptions in C# generally requires a try-catch statement.
The syntax is essentially as follows:
try
{
// operation likely to cause error
}
catch (Exception e){
// handle error
Console.WriteLine("Exception: " + e);
}
Console.Read();
So wrap your con.Open() logic in a try-catch statement like so:
try
{
Con.Open();
}
catch (Exception e){
// handle error
Console.WriteLine("Possible MySQL Exception: " + e);
}
Additionally, you can add a finally block to the end of a try-catch statement, which executes its code regardless of whether an exception was handled or not:
try
{
// attempt to do something here
con.Open();
}
catch (Exception e){
// handle error
Console.Writeline("Exception: " + e);
}
finally
{
Console.Writeline("This runs no matter if an exception is thrown or not!");
}
Console.Read();
Please accept my apologies if I'm getting my verbiage wrong; I'm just now learning C# (my background is mostly Visual Basic and PHP).
What I'm trying to do is create a class / routine in C# (Windows Forms) for connecting and disconnecting to a MySQL database that can then be reused throughout the rest of my project without having to reiterate the code every time.
I've got my class / routine setup, but I'm stuck on trying to call it from the rest of my project. I know in Visual Basic this was a fairly simple task to do, but I just can't seem to figure it out how to do it in C#.
Any suggestions? Thank you in advance.
public void dbDisconnect(object sender, EventArgs e)
{
try
{
MySqlConnection connection = new MySqlConnection(Properties.Settings.Default.mysql_db_conn_string);
connection.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Here's a method I currently have in my app:
public static MySqlConnection CreateConnection(
string mysqlServer,
string mysqlUser,
string mysqlPassword,
string mysqlDatabase)
{
MySqlConnection mysqlConnection = null;
string mysqlConnectionString = String.Format(
"server={0};uid={1};pwd={2};database={3};DefaultCommandTimeout={4};",
mysqlServer, mysqlUser, mysqlPassword, mysqlDatabase, 120);
/**
** Workaround for MySQL 5.6 bug:
** http://stackoverflow.com/questions/30197699/reading-from-stream-failed-mysql-native-password-error
*/
int tryCounter = 0;
bool isConnected = false;
do
{
tryCounter++;
try
{
mysqlConnection = new MySqlConnection();
mysqlConnection.ConnectionString = mysqlConnectionString;
mysqlConnection.Open();
if (mysqlConnection.State == ConnectionState.Open)
{
isConnected = true;
}
}
catch (MySqlException ex)
{
if (tryCounter < 10)
{
DebugLog.Dump(ex.ToString(), DebugLog.MainLogFilePath);
Thread.Sleep(10000); // 10 seconds.
}
else
{
throw;
}
}
} while (!isConnected);
return mysqlConnection;
}
Usage:
using (MySqlConnection hostsDbConnection = HostsDbConnector.CreateConnection())
{
// Do something...
}
With using keyword you don't need to close the connection manually, it'll be closed automatically when it's no longer needed.
I have a VS2013 (written in C# x32) desktop application accessing a hosted SQL Server 2012. It has a report that has 4 subreports. After I installed it onto a few PCs, One of the PC has the above issue but the other PCs display the report correctly. The strange thing is the problem PC display this error half-way through subreport4. All PCs are running on Windows 7 (x32/64). I am really at a lost as to how to find out why it happened only to 1 PC which is basically similar to the rest.
The coding of the report is reproduced below:-
public partial class ReportProject : Form
{
cl_Class1 mySettings = new cl_Class1();
SqlConnection conReport = new SqlConnection();
public ReportProject()
{
InitializeComponent();
this.Text = "Test Report";
// Add a handler for SubreportProcessing
reportViewer1.LocalReport.SubreportProcessing += new SubreportProcessingEventHandler(LocalReport_SubreportProcessing);
}
// data set at the class level to access by all methods
DataSet dsReport = new dsTestReport();
private void ReportProject_Load(object sender, EventArgs e)
{
// connection to database
conReport.ConnectionString = mySettings.myConnString;
SqlCommand cmdReport = new SqlCommand();
SqlDataReader drReport;
try
{
// open connection
conReport.Open();
cmdReport.CommandType = CommandType.Text;
cmdReport.Connection = conReport;
// get query string from builder
string strMain = "aaaaa";
string strSub1 = "bbbbb";
string strSub2 = "ccccc";
string strSub3 = "ddddd";
cmdReport.CommandText = strMain + strSub1 + strSub2 + strSub3;
// execute query and load result to dataset
drReport = cmdReport.ExecuteReader();
dsReport.Load(drReport, LoadOption.OverwriteChanges, dsReport.Tables[0], dsReport.Tables[1], dsReport.Tables[2], dsReport.Tables[3]);
// close connection
drReport.Close();
conReport.Close();
// prepare report for view
reportViewer1.LocalReport.ReportEmbeddedResource = "myProgram.rptMain.rdlc";
ReportDataSource rds = new ReportDataSource();
rds.Name = "DataSet1";
rds.Value = dsReport.Tables[0];
reportViewer1.LocalReport.DataSources.Add(rds);
// preview the report
reportViewer1.RefreshReport();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
if (conReport.State == ConnectionState.Open)
{
conReport.Close();
}
}
}
void LocalReport_SubreportProcessing(object sender, SubreportProcessingEventArgs e)
{
string myReportName = e.ReportPath;
if (myReportName == "rptSubReport1")
{
e.DataSources.Add(new ReportDataSource("DataSet1", dsReport.Tables[1]));
}
if (myReportName == "rptSubReport2")
{
e.DataSources.Add(new ReportDataSource("DataSet1", dsReport.Tables[2]));
}
if (myReportName == "rptSubReport3")
{
e.DataSources.Add(new ReportDataSource("DataSet1", dsReport.Tables[3]));
}
if (myReportName == "rptSubReport4")
{
e.DataSources.Add(new ReportDataSource("DataSet1", dsReport.Tables[3]));
}
}
}
NOTE: SubReport3 and SubReport4 uses the same dataset (dsReport.Tables[3])
Would apprecate advise/help to resolve this.
Thank you in advance!
As a last resort, I uninstalled the reportviewer runtime from this PC (this is the only PC with a copy of the reportviewer). After the uninstall, the report now runs correctly! although this seemed to resolve the issue, I am still puzzled why this is the case - maybe there is something in the reportviewer runtime that conflict with the compiled software.
We have been dealing with an error for the last couple of days, so we created a small page (quick and dirty programming, my apologies in advance) that connects to the database, checks if a document exists, and displays some data related to the document. If there is an exception, an email is sent with the exception information and some log data.
Here's a simplified version of the code (short explanation below):
namespace My.Namespace
{
public partial class myClass : System.Web.UI.Page
{
private static SqlConnection conn = null;
private static SqlCommand command1 = null;
private static SqlCommand command2 = null;
private static string log = "";
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
try
{
log += "START\n";
string docId = Request.QueryString["docId"];
if (!String.IsNullOrEmpty(docName))
{
bool docExists = doesDocExist(docId);
if (docExists == true)
{
string docMetadata = getMetadata(docId);
Response.Write(docMetadata);
}
}
else
{
// display error message
}
}
catch (sqlException sqlex)
{
// process exception
sendErrorMessage(sqlex.Message);
}
catch (Exception ex)
{
// process exception
sendErrorMessage(ex.Message);
}
}
}
private static bool doesDocExist(string docId)
{
log += "In doesDocExist\n";
bool docExists = false;
try
{
// open db connection (conn)
string cmd = String.Format("SELECT COUNT(*) FROM docs WHERE id='{0}'", docId);
command1 = new SqlCommand(cmd, conn);
conn.Open();
var val = command1.ExecuteScalar();
int numberOfRows = int.Parse(val.ToString());
if (numberOfRows > 0) { docExists = true; }
}
finally
{
// close db connection (conn)
}
return docExists;
}
protected string getMetadata(string docId)
{
log += "In getMetadata\n";
string docMetadata = "";
try
{
// open db connection (conn)
string cmd = String.Format("SELECT metadata FROM docs WHERE id='{0}'", docID);
command2 = new SqlCommand(cmd, conn);
conn.Open();
SqlDataReader rReader = command2.ExecuteReader();
if (rReader.HasRows)
{
while (rReader.Read())
{
// process metadata
docMetadata += DOCMETADATA;
}
}
}
return docMetadata;
}
public static void sendErrorMessage(string messageText)
{
HttpContext.Current.Response.Write(messageText);
// Send string log via email
}
}
}
I know it's too long, so here is a quick description of it. We have a class with the Page_Load method and three other methods:
doesDocExists: returns a bool value indicating if an document ID is in the database.
getMetadata: returns a string with metadata related to the document.
sendErrorMessage: sends an email with a log generated during the page.
From Page_Load we call doesDocExists. If the value returned is true, then it calls getMetadata and displays the value on the screen. If there's any error, it is caught in the Page_Load and sent as an email.
The problem is that when there's an error, instead of getting an email with the log (i.e.: START - In Function1 - In Function2), the log appears 100 times in the email (i.e.: START - In Function1 - In Function2 - Start - In Function1 - In Function2 - START... and so on), as if Page_Load was fired that many times.
We read online (http://www.craigwardman.com/blog/index.php/2009/01/asp-net-multiple-page-load-problem/) that it could be because of the PostBack. So, we added the condition if (!Page.IsPostBack), but the result is still the same.
Is there any reason why Page_Load would be triggered multiple times? Or is it that we are doing something wrong with the log variable and/or the try/catch that causes this behavior?
The log may be long because you are declaring the string log as static. Does it need to be static?
private static SqlConnection conn = null;
private static SqlCommand command1 = null;
private static SqlCommand command2 = null;
private static string log = "";
The problem is that log is Singleton along with other properties.
Whenever you access that page, you append text to log property which ends up being START - In Function1 - In Function2 - Start - In Function1 - In Function2 - START... and so on
Base on your scenario, you do not need to use Singleton inside myClass.
FYI: Since I do not know the rest of your code, ensure to instantiate conn, command1, command2.
If your page load functions are execute twice because post back is possible when you clicking on the button or link, so should check it and run by the below
if (!IsPostBack)
{
try
{
log += "START\n";
string docId = Request.QueryString["docId"];
if (!String.IsNullOrEmpty(docName))
{
bool docExists = doesDocExist(docId);
if (docExists == true)
{
string docMetadata = getMetadata(docId);
Response.Write(docMetadata);
}
}
else
{
// display error message
}
}
catch (sqlException sqlex)
{
// process exception
sendErrorMessage(sqlex.Message);
}
catch (Exception ex)
{
// process exception
sendErrorMessage(ex.Message);
}
}
}
I have a buttton on the click event of which I am calling a function.I have set the accept button property to that button.But it is not firing the event on single click.
private void btnConnect_Click(object sender, EventArgs e)
{
try
{
//Function call for validating the textboxes entry
ValidateForm();
if(lblMessage.Text != string.Empty)
{
//Function call for binding the dropdown with all DB names
BindDBDropDown();
//Function call for binding the operation names in dropdown
SetOperationDropDown();
}
else
{
//Else give the error message to user
lblMessage.Text = "Invalid Credentials";
}
}
catch(Exception ex)
{
//All the exceptions are handled and written in the EventLog.
EventLog log = new EventLog("Application");
log.Source = "MFDBAnalyser";
log.WriteEntry(ex.Message);
}
}
public void BindDBDropDown()
{
SqlConnectionStringBuilder objConnectionString = new SqlConnectionStringBuilder();
objConnectionString.DataSource = txtHost.Text;
objConnectionString.UserID = txtUsername.Text;
objConnectionString.Password = txtPassword.Text;
SqlConnection sConnection = new SqlConnection(objConnectionString.ConnectionString);
//If connected then give this message to user
lblMessage.Visible = true;
lblMessage.Text = "You are connected to the SQL Server....";
try
{
//To Open the connection.
sConnection.Open();
//Query to select the list of databases.
string selectDatabaseNames = #"SELECT
NAME
FROM
[MASTER]..[SYSDATABASES]";
//Create the command object
SqlCommand sCommand = new SqlCommand(selectDatabaseNames, sConnection);
//Create the data set
DataSet sDataset = new DataSet("master..sysdatabases");
//Create the dataadapter object
SqlDataAdapter sDataAdapter = new SqlDataAdapter(selectDatabaseNames, sConnection);
sDataAdapter.TableMappings.Add("Table", "master..sysdatabases");
//Fill the dataset
sDataAdapter.Fill(sDataset);
//Bind the database names in combobox
DataViewManager dsv = sDataset.DefaultViewManager;
//Provides the master mapping between the sourcr table and system.data.datatable
cmbDatabases.DataSource = sDataset.Tables["master..sysdatabases"];
cmbDatabases.DisplayMember = "NAME";
cmbDatabases.ValueMember = ("NAME");
}
catch(Exception ex)
{
//All the exceptions are handled and written in the EventLog.
EventLog logException = new EventLog("Application");
logException.Source = "MFDBAnalyser";
logException.WriteEntry(ex.Message);
MessageBox.Show ("Login Failed!!", "Error Occured");
}
finally
{
//If connection is not closed then close the connection
if(sConnection.State != ConnectionState.Closed)
{
sConnection.Close();
}
}
}
Can anybody help me out??
Uh, on the first click, does lblMessage contain any text?
Because if not, the first time you run it, it will fail the conditional test and insert the string "Invalid Credentials" into the label. Then, the second time you run it, it will pass the conditional test and call the BindDBDropDown method as you're expecting.
Specifically, this section of your code:
if(lblMessage.Text != string.Empty)
{
//Function call for binding the dropdown with all DB names
BindDBDropDown();
//Function call for binding the operation names in dropdown
SetOperationDropDown();
}
else
{
//Else give the error message to user
lblMessage.Text = "Invalid Credentials";
}
I assume that you're either trying to check that the contents of a textbox where the user has entered their credentials are not empty, or that you want to make sure an error message is not currently displayed in lblMessage. Make sure that your code accurately reflects your intentions!