I've created a class that confirms if it's able to connect to a db on mysql using login info provided via string CadenaConexion. How can I process an additional db and have the code connect to both when executing?
First I create a connection and assign the login info (here is where I'd add the second db):
using MySql.Data.MySqlClient;
namespace DBManager
{
public class DBConexion
{
protected MySqlConnection oConexion;
String CadenaConexion = "Server=localhost; Port=3306;Database=blabla;Uid=root;Pwd=blabla; AllowZeroDateTime=True;";
string _estado;
public string Estado
{
get => _estado;
}
Then I determine if connected or not through a boolean variable:
public Boolean Conectar()
{
Boolean Conectado = false;
oConexion = new MySqlConnection(CadenaConexion);
try
{
oConexion.Open();
Conectado = true;
}
catch
{
Conectado = false;
}
_estado = oConexion.State.ToString();
return Conectado;
}
Optional method to confirm if successful, as it will not perform the disconnect unless it was previously connected:
public void Desconectar()
{
try
{
if (oConexion.State == System.Data.ConnectionState.Open)
{
try
{
oConexion.Close();
}
catch
{
}
}
_estado = oConexion.State.ToString();
}
catch
{
_estado = "Indefinido";
}
}
Related
I would like send connection for report in DevExpress, and send query for this report I call report with code bellow:
private void Form14_Load(object sender, EventArgs e)
{
try {
XtraReport report = XtraReport.FromFile(#"C:\\a\\Report2.repx", true);
ReportPrintTool printTool = new ReportPrintTool(report);
printTool.ShowPreviewDialog();
}
catch (Exception ex) {
MessageBox.Show(ex.ToString());
}
}
In the general case, your report is connected to data via the SqlDataSource component. So, I suggest you update the connection at the SqlDataSource instance level. For that purpose, just get the existing data source from your XtraReport class:
var sqlDataSource = xtraReport.DataSource as SqlDataSource;
sqlDataSource.ConnectionParameters = ...;
Please refer to the Specify data connection article to learn how to change the data source's connection parameters.
You can create your own report implementation where you can update the connection string by checking the connection strings used in the reports and the sub reports.
In below example, a Typed Dataset is used to create the reports and then you can update the connection string of the table adapters on the initialization.
Refere this below implementation:
// Base Report
public partial class BaseReport: DevExpress.XtraReports.UI.XtraReport, IDisposable
{
public List<SQLiteConnection> GetConnectionList
{
get { return connectionList; }
}
public List<SimergyBaseReport> GetSubReportList
{
get { return subReportList; }
}
protected List<SQLiteConnection> connectionList = new List<SQLiteConnection>();
protected List<SimergyBaseReport> subReportList = new List<SimergyBaseReport>();
public void UpdateConnectionString(String connectionString)
{
#if !RPT_DESIGN
connectionString = GlobalUtilities.GetOutputConnectionString(connectionString);
foreach (SQLiteConnection conn in connectionList)
{
conn.Close();
conn.ConnectionString = connectionString;
reportDataSet.Clear();
}
foreach (BaseReport subReport in comparisonSubReportList)
{
if (subReport != null)
subReport.UpdateConnectionString(connectionString);
}
#endif
}
}
// Report
public partial class UsageSummary : Simergy.Reporting.Reports.BaseReport
{
public ClimaticSummary()
{
InitializeComponent();
}
public ClimaticSummary(String connectionString, Model model)
: base(model)
{
InitializeComponent();
connectionList.Add(applicationUsageTableAdapter.Connection);
connectionList.Add(dailyUsage_SUMMARYTableAdapter.Connection);
subReportList.Add(xrSubreport1.ReportSource as BaseReport);
subReportList.Add(xrSubreport2.ReportSource as BaseReport);
subReportList.Add(footerSubReport.ReportSource as BaseReport);
reportDataSet = report_DataSet1;
UpdateConnectionString(connectionString);
}
}
// Custom print control to render the reports
public partial class ReportViewControl : PrintControl
{
private SimergyBaseReport CurrentReport = null;
public ReportViewControl()
{
InitializeComponent();
}
public void SetReport(SimergyBaseReport report)
{
CurrentReport = report;
if (CurrentReport != null)
{
this.PrintingSystem = report.PrintingSystem;
SetupButtonVisability();
report.CreateDocument();
report.RecreateDocumentMap();
this.PrintingSystem = report.PrintingSystem;
}
}
public void RefreshReport()
{
this.PrintingSystem = null;
this.PrintingSystem = CurrentReport.PrintingSystem;
CurrentReport.CreateDocument(true);
}
}
///Usage
BaseReport report = new UsageSummary(someConnectionString);
ReportViewControl viewer = new ReportViewControl();
viewer.SetReport(report);
form1.Controls.Add(viewer);
I have created a class UserInfo and I have set values on user login response, now I don't know how to access those values in another part of my app (another form).
Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MYCUSTOMAPP
{
class UserInfo
{
public string userId;
public string userType;
public string userName;
public string userUserName;
public string userPhone;
public string userIdCard;
}
}
Login (set values to class stings)
//....
SqlDataReader result = cmd.ExecuteReader();
if (result.HasRows)
{
while (result.Read())
{
UserInfo loggedUser = new UserInfo();
loggedUser.userId = result.GetValue(result.GetOrdinal("Id")).ToString();
loggedUser.userName = result.GetValue(result.GetOrdinal("Name")).ToString();
loggedUser.userType = result.GetValue(result.GetOrdinal("UserType")).ToString();
loggedUser.userUserName = result.GetValue(result.GetOrdinal("UserName")).ToString();
loggedUser.userPhone = result.GetValue(result.GetOrdinal("Phone")).ToString();
loggedUser.userIdCard = result.GetValue(result.GetOrdinal("IdCard")).ToString();
}
}
// the rest...
Question
Now let say I am in MainWindow form, how can I get value of userId for instance?
Update
Logic
User login
Store user data in class (or anything else that you might suggest)
Get those user data globally in my app so I don't need to call database each time I need user info (it will be presented already)
Update 2
My login function
using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["MYCUSTOMAPPDatabaseString"].ConnectionString))
{
if (cn.State == ConnectionState.Closed)
cn.Open();
using (DataTable dt = new DataTable())
{
using (SqlCommand cmd = new SqlCommand("dbo.LoginUser", cn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#UserName", usernameBox.Text);
cmd.Parameters.AddWithValue("#Password", passwordBox.Text);
SqlDataReader result = cmd.ExecuteReader();
if (result.HasRows)
{
while (result.Read())
{
// Name of logged user from database (this is database response)
Console.WriteLine(result.GetValue(result.GetOrdinal("Name")));
// Add logged user info to `UserInfo` class
UserInfo loggedUser = new UserInfo();
loggedUser.userId = result.GetValue(result.GetOrdinal("Id")).ToString();
loggedUser.userName = result.GetValue(result.GetOrdinal("Name")).ToString();
loggedUser.userType = result.GetValue(result.GetOrdinal("UserType")).ToString();
loggedUser.userUserName = result.GetValue(result.GetOrdinal("UserName")).ToString();
loggedUser.userPhone = result.GetValue(result.GetOrdinal("Phone")).ToString();
loggedUser.userIdCard = result.GetValue(result.GetOrdinal("IdCard")).ToString();
MainWindow mainWindow = new MainWindow();
this.Hide();
mainWindow.ShowDialog();
Show();
}
}
else
{
cn.Close();
MessageBox.Show("Your credentials are not match!", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
I think you can pass it as the parameters when you call another form's constructor, if you directly call that form. Like in this case : Communicate between two windows forms in C#
However, if you need to load it later on, you can either store it as user settings: https://www.youtube.com/watch?v=P432z8q9iVE. Or even more structural approach is store the data in database like MySQL, MSSQL, or another database that you can put when user click the call to action button.
Solved
I have changed my class to the following
class UserInfo
{
private string userId1;
private static string userType1;
private static string userName1;
private static string userUserName1;
private static string userPhone1;
private static string userIdCard1;
public string GetuserId()
{
return userId1;
}
public void SetuserId(string value)
{
userId1 = value;
}
public string GetuserType()
{
return userType1;
}
public void SetuserType(string value)
{
userType1 = value;
}
public string GetuserName()
{
return userName1;
}
public void SetuserName(string value)
{
userName1 = value;
}
public string GetuserUserName()
{
return userUserName1;
}
public void SetuserUserName(string value)
{
userUserName1 = value;
}
public string GetuserPhone()
{
return userPhone1;
}
public void SetuserPhone(string value)
{
userPhone1 = value;
}
public string GetuserIdCard()
{
return userIdCard1;
}
public void SetuserIdCard(string value)
{
userIdCard1 = value;
}
}
And changed my code in login response to:
while (result.Read())
{
UserInfo loggedUser = new UserInfo();
loggedUser.SetuserId(result.GetValue(result.GetOrdinal("Id")).ToString());
loggedUser.SetuserName(result.GetValue(result.GetOrdinal("Name")).ToString());
loggedUser.SetuserType(result.GetValue(result.GetOrdinal("UserType")).ToString());
loggedUser.SetuserUserName(result.GetValue(result.GetOrdinal("UserName")).ToString());
loggedUser.SetuserPhone(result.GetValue(result.GetOrdinal("Phone")).ToString());
loggedUser.SetuserIdCard(result.GetValue(result.GetOrdinal("IdCard")).ToString());
}
Now I can get my values in any form like:
UserInfo loggedUser = new UserInfo();
loggedUser.GetuserName(); // will return logged user name
I have first time implemented signalR concept and its working when page load first time and when I perform any insert, delete or updated operation on the database it calls a method which is specified in code but I am getting the null value of Context.User.Identity.Name. I have used FormAuthentication and after logged in I am getting connectionId and username but after make changes on a table of database getting the null value of username. Below I have mentioned my code.
HubClass
namespace SCPLTabAssessPortal
{
public class User
{
public string Name { get; set; }
public HashSet<string> ConnectionIds { get; set; }
}
[Authorize]
public class DashboardNewHub : Hub
{
int totalNewMessages = 0;
int ttltdy = 0;
int Ttlnum = 0;
int totalNewNotification = 0;
private static readonly ConcurrentDictionary<string, User> Users = new ConcurrentDictionary<string, User>();
public override Task OnConnected()
{
string userName = Context.User.Identity.Name;
string connectionId = Context.ConnectionId;
var user = Users.GetOrAdd(userName, _ => new User
{
Name = userName,
ConnectionIds = new HashSet<string>()
});
lock (user.ConnectionIds)
{
user.ConnectionIds.Add(connectionId);
Clients.AllExcept(user.ConnectionIds.ToArray()).userConnected(userName);
// TODO: Broadcast the connected user
}
return base.OnConnected();
}
public override Task OnDisconnected(bool stopCalled)
{
string name = Context.User.Identity.Name;
User rmuser;
Users.TryRemove(name, out rmuser);
return base.OnDisconnected(stopCalled);
}
public override Task OnReconnected()
{
string name = Context.User.Identity.Name;
string connectionId = Context.ConnectionId;
var user = Users.GetOrAdd(name, _ => new User
{
Name = name,
ConnectionIds = new HashSet<string>()
});
lock (user.ConnectionIds)
{
user.ConnectionIds.Add(connectionId);
Clients.AllExcept(user.ConnectionIds.ToArray()).userConnected(name);
// TODO: Broadcast the connected user
}
return base.OnReconnected();
}
[HubMethodName("sendNotifications")]
public string SendNotifications()
{
IEnumerable<string> allReceivers = null;
try
{
User getuser = GetUser(Context.User.Identity.Name);
using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["SCPLDBPortalConnectionString"].ConnectionString))
{
string query = "SELECT [ColumnName],[ColumnName] FROM [dbo].[TableName] ";
connection.Open();
using (SqlCommand command = new SqlCommand(query, connection))
{
try
{
command.Notification = null;
DataTable dt = new DataTable();
SqlDependency dependency = new SqlDependency(command);
dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
if (connection.State == ConnectionState.Closed)
connection.Open();
var reader = command.ExecuteReader();
dt.Load(reader);
if (dt.Rows.Count > 0)
{
int totaltax = 0;
foreach (DataRow r in dt.Rows)
{
totaltax += (string.IsNullOrEmpty(Convert.ToString(r["TaxTotal"])) ? 0 : Convert.ToInt32(r["TaxTotal"]));
}
totalNewMessages = totaltax;
}
connection.Close();
}
catch (Exception ex)
{
throw;
}
}
}
User receiver;
if (Users.TryGetValue(getuser.Name, out receiver))
{
User sender = GetUser(Context.User.Identity.Name);
lock (receiver.ConnectionIds)
{
lock (sender.ConnectionIds)
{
allReceivers = receiver.ConnectionIds.Concat(sender.ConnectionIds);
}
}
foreach (var cid in allReceivers)
{
Clients.Client(cid).received(totalNewMessages);
}
}
}
catch (Exception ex) {
}
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<DashboardNewHub>();
return (string)context.Clients.Client(Convert.ToString(allReceivers.Last())).RecieveNotification(totalNewMessages).Result;
}
private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
if (e.Type == SqlNotificationType.Change)
{
DashboardNewHub nHub = new DashboardNewHub();
nHub.SendNotifications();
}
}
private User GetUser(string username)
{
User user;
Users.TryGetValue(username, out user);
return user;
}
}
}
JqueryCode
jQuery(document).ready(function () {
// Declare a proxy to reference the hub.
var notifications = $.connection.dashboardNewHub;
// Create a function that the hub can call to broadcast messages.
notifications.client.recieveNotification = function (totalNewMessages, ttltdy) {
$('#TtlColl').text(totalNewMessages);
};
// Start the connection.
$.connection.hub.start().done(function () {
notifications.server.sendNotifications();
}).fail(function (e) {
alert(e);
});
});
Global.asax.cs
protected void Application_Start(object sender, EventArgs e)
{
SqlDependency.Start(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
}
protected void Application_End(object sender, EventArgs e)
{
SqlDependency.Stop(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
}
Login.cs
The below code I wrote while a user is logging in.
FormsAuthentication.RedirectFromLoginPage(txtUserName.Text, true);
FormsAuthentication.SetAuthCookie(txtUserName.Text + "$" + DS.Tables[0].Rows[i]["ID"].ToString(), true);
The point is because is the sql broker engine to call nHub.SendNotifications() you can't get any informations about the user logged-in as is not the user logged is making the request
How can i sign-out and redirect to the login page from a public static class?
I have tried the following but it does not stop page execution..
public static DatabaseNameEntities CreateEntitiesForSpecificDatabaseName(bool contextOwnsConnection = true)
{
string database_name = "";
try
{
database_name = System.Web.HttpContext.Current.Application["DB_NAME"].ToString();
}
catch (NullReferenceException)
{
FormsAuthentication.SignOut();
FormsAuthentication.RedirectToLoginPage();
}
//Initialize the SqlConnectionStringBuilder
//Initialize the EntityConnectionStringBuilder
//Create entity connection
EntityConnection connection = new EntityConnection(entityBuilder.ConnectionString);
return new DatabaseNameEntities(connection);
}
I have tried the following but it does not stop page execution..
That's because it's simply not the MVC way. It's also breaks the Single Responsibility Principle, that is, why would a method named CreateEntitiesForSpecificDatabaseName() know anything about MVC or logging out a user. The code you posted generally breaks this principle multiple times (application state, signing out a user).
Additionally, catching an exception you can prevent is also poor practice (or as the Lead Developer for the C# Compiler team called it, Boneheaded Exceptions).
Consider the following code.
public static ControllerBaseExtensions
{
private const string DBNAME = "DB_NAME";
public static bool TryGetDatabaseName(this ControllerBase instance,
out string DbName)
{
DbName = null;
var app = GetApp(instance);
var result = app.Any(k => k == DBNAME);
if (result)
{
DbName = instance.Application[DBNAME] as string;
result = DbName != null;
}
return result;
}
public static void SetDatabaseName(this ControllerBase instance,
string DbName)
{
var app = GetApp(instance);
app[DBNAME] = DbName;
}
private static HttpApplication GetApp(ControllerBase instance)
{
return instance.ControllerContext.HttpContext.Application;
}
}
public ActionResult MyMethod()
{
string DbName;
if (!this.TryGetDatabaseName(out DbName))
{
FormsAuthentication.SignOut();
// http://stackoverflow.com/questions/30509980
RedirectToAction("Login", "Account");
}
CreateEntitiesForSpecificDatabaseName(Dbname);
}
public static DatabaseNameEntities CreateEntitiesForSpecificDatabaseName(
string dbName,
bool contextOwnsConnection = true)
{
//Initialize the SqlConnectionStringBuilder
//Initialize the EntityConnectionStringBuilder
//Create entity connection
EntityConnection connection = new
EntityConnection(entityBuilder.ConnectionString);
return new DatabaseNameEntities(connection);
}
Does simply ie, no try or catch work as expected
public static DatabaseNameEntities CreateEntitiesForSpecificDatabaseName(bool contextOwnsConnection = true)
{
FormsAuthentication.SignOut();
FormsAuthentication.RedirectToLoginPage();
}
I have the following code to test DB connection, it runs periodically to test for DB availability:
private bool CheckDbConn()
{
SqlConnection conn = null;
bool result = true;
try
{
conn = DBConnection.getNewCon();
ConnectionState conState = conn.State;
if (conState == ConnectionState.Closed || conState == ConnectionState.Broken)
{
logger.Warn(LogTopicEnum.Agent, "Connection failed in DB connection test on CheckDBConnection");
return false;
}
}
catch (Exception ex)
{
logger.Warn(LogTopicEnum.Agent, "Error in DB connection test on CheckDBConnection", ex);
return false; // any error is considered as db connection error for now
}
finally
{
try
{
if (conn != null)
{
conn.Close();
}
}
catch (Exception ex)
{
logger.Warn(LogTopicEnum.Agent, "Error closing connection on CheckDBConnection", ex);
result = false;
}
}
return result;
}
And:
static public SqlConnection getNewCon()
{
SqlConnection newCon = new SqlConnection();
newCon.ConnectionString = DBConnection.ConnectionString; // m_con.ConnectionString;
newCon.Open();
return newCon;
}
My question is: will this work as expected?
Specifically, I'm concerned about the test of the ConnectionState. Is it possible that the state will be: connecting (since Open() is synchronous)?
What should I do in that case?
You can try like this.
public bool IsServerConnected()
{
using (var l_oConnection = new SqlConnection(DBConnection.ConnectionString))
{
try
{
l_oConnection.Open();
return true;
}
catch (SqlException)
{
return false;
}
}
}
SqlConnection will throw a SqlException when it cannot connect to the server.
public static class SqlExtensions
{
public static bool IsAvailable(this SqlConnection connection)
{
try
{
connection.Open();
connection.Close();
}
catch(SqlException)
{
return false;
}
return true;
}
}
Usage:
using(SqlConnection connection = GetConnection())
{
if(connection.IsAvailable())
{
// Success
}
}
Your code seems fine, but you really need to use the IDisposable pattern, and some naming convention too:
private bool CheckDbConnection(string connectionString)
{
try
{
using(var connection = new SqlConnection(connectionString))
{
connection.Open();
return true;
}
}
catch (Exception ex)
{
logger.Warn(LogTopicEnum.Agent, "Error in DB connection test on CheckDBConnection", ex);
return false; // any error is considered as db connection error for now
}
}
And connection.Close() is not supposed to throw. Just use the using block and your are fine.
No need to test the Close state, since you have just opened it.
More about the Broken state:
Broken The connection to the data source is broken. This can occur
only after the connection has been opened. A connection in this state
may be closed and then re-opened. (This value is reserved for future
versions of the product.)
So really, no need to test that.
The Connecting state could be catch if you are in a multithread context and your instance of connection is shared. But it is not your case here.
This code does not block a UI if called.
public static class DatabaseExtensions
{
public static async Task<bool> IsConnectionViable(this string connectionStr)
{
await using var sqlConn = new SqlConnection(connectionStr);
return await sqlConn.IsConnectionViable();
}
public static async Task<bool> IsConnectionViable(this SqlConnection connection)
{
var isConnected = false;
try
{
await connection.OpenAsync();
isConnected = (connection.State == ConnectionState.Open);
}
catch (Exception)
{
// ignored
}
return isConnected;
}
}
actually, in visual studio, connection class has sonnectionstate property.
when connection state changes, connections statechange event is been trigerred.
you might want to check this article.
https://msdn.microsoft.com/en-us/library/aa326268(v=vs.71).aspx
I was using #Ramesh Durai's solution but found that on my setup at least (the app calling/testing periodically after the app had started; using .Net 3.5 with Sql Server 2012 database) that the first call to IsConnected() after taking the database offline was returning true. However, it was throwing the expected exception on the ExecuteScalar() line below:
public bool IsConnected() {
using (var conn = new SqlConnection(DBConnection.ConnectionString)) {
using (var cmd = New SqlCommand("SELECT 1", conn)) {
try {
conn.Open();
cmd.ExecuteScalar();
return true;
} catch (SqlException) {
return false;
}
}
}
}
This code is for Mysql.
public class Program
{
string connection = "SERVER=localhost; user id=root; password=; database=dbname";
private void Form1_Load(object sender, System.EventArgs e)
{
checkifconnected();
}
private void checkifconnected()
{
MySqlConnection connect = new MySqlConnection(connection);
try{
connect.Open();
MessageBox.Show("Database connected");
}
catch
{
MessageBox.Show("you are not connected to database");
}
}
public static void Main()
{
}
}