UPD:
I have a static class for work with database.
This class contains the method which returns connect to database. Early this method returns connect to Advantage database (AdsConnection):
static private AdsConnection GetConnection(){
var conn = new AdsConnection();
conn.ConnectionString = here my connection string
return conn;
}
Now, I need to change this method. I need that this method returns connect to different databases types (Advantage database, Oracle database).
The method will work into public methods in my class. For example, method for get data from any table from database.
public static List<entity1> GetEntities(){}
Into this method the first of my step is to resolve the type of database, then connect to database. Then get data from database and the last step is return data (List< entity1 >).
In the step to connect the database I need to use the method GetConnection("Ads")
This method returns current connect to database and then I can use this connect for work
I changed method:
My first version
static private T GetConnection<T>(string dbType)
{
if (dbType.Equals("Oracle"))
{
OdbcConnection conn = new OdbcConnection
conn.ConnectionString = here my connection string
return (T)conn;
}
if (dbType.Equals("Ads"))
{
AdsConnection conn = new AdsConnection
conn.ConnectionString = here my connection string
return (T)conn;
}
return default(T);
}
But, my solution does not work. I have errors:
Cannot convert type 'System.Data.Odbc.OdbcConnection' to 'T'
Cannot convert type 'Advantage.Data.Provider.AdsConnection' to 'T'
I do not know how to resolve my problem.
Please, tell me how to resolve my problem?
Now, I use the following code (this solution give me #khlr):
static private IDbConnection GetConnection(string dbType)
{
if (dbType.Equals("Oracle"))
{
OdbcConnection conn = new OdbcConnection
conn.ConnectionString = here my connection string
return conn;
}
if (dbType.Equals("Ads"))
{
AdsConnection conn = new AdsConnection
conn.ConnectionString = here my connection string
return conn;
}
return null;
}
Thank.
One way you can abstract the connection instantiation is by using DbProviderFactory of ADO.Net. You can basically pass it a provider name and it will give a connection based on the provider. This basically reduce the check of dbtype etc for you and I think its sensible approach when you need to target multiple database. Some of the code snippet are copied from MSDN.
In you config file you can multiple connection string set up with different database type and provider.
<configuration>
<add name="NorthwindAccess"
providerName="System.Data.OleDb"
connectionString=
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Data\Northwind.mdb;"
/>
Then in you method you can do following:
static DbConnection CreateDbConnection(
string providerName, string connectionString)
{
// Assume failure.
DbConnection connection = null;
// Create the DbProviderFactory and DbConnection.
if (connectionString != null)
{
try
{
DbProviderFactory factory =
DbProviderFactories.GetFactory(providerName);
connection = factory.CreateConnection();
connection.ConnectionString = connectionString;
}
catch (Exception ex)
{
// Set the connection to null if it was created.
if (connection != null)
{
connection = null;
}
Console.WriteLine(ex.Message);
}
}
// Return the connection.
return connection;
}
You could do the following, since both connections inherit from IDbConnection:
static private IDbConnection GetConnection(string dbType)
{
if (dbType.Equals("Oracle"))
{
OdbcConnection conn = new OdbcConnection
conn.ConnectionString = here my connection string
return conn;
}
if (dbType.Equals("Ads"))
{
AdsConnection conn = new AdsConnection
conn.ConnectionString = here my connection string
return conn;
}
return null;
}
Related
I have the following SQL helper class:
public class SqlHelper
{
SqlConnection cn;
public SqlHelper(string connectionString)
{
cn = new SqlConnection(connectionString);
}
public bool isConnection
{
get
{
if (cn.State == System.Data.ConnectionState.Closed)
cn.Open();
return true;
}
}
}
I also have two connection strings:
string connectionString = string.Format("Data Source={0};Initial Catalog={1};User ID={2};Password={3};", Variables.setDb1ServerName, Variables.setDb1Name, Variables.setDb1User, Variables.setDb1Password);
string connectionString2 = string.Format("Data Source={0};Initial Catalog={1};User ID={2};Password={3};", Variables.setDb2ServerName, Variables.setDb2Name, Variables.setDb2User, Variables.setDb2Password);
What I want to do is create two buttons that will check if the respective connection is active.
My attempt is below - button one:
private void txtConnection1_Click(object sender, EventArgs e)
{
string connectionString = string.Format("Data Source={0};Initial Catalog={1};User ID={2};Password={3};", Variables.setDb1ServerName, Variables.setDb1Name, Variables.setDb1User, Variables.setDb1Password);
try
{
SqlHelper helper = new SqlHelper(connectionString);
if (helper.isConnection)
MessageBox.Show("Конекцијата е успешна", "Порака", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch(Exception ex)
{
MessageBox.Show(ex.Message, "Порака", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
I've also create a second button, that connects to ConnectionString2 with SqlHelper helper2 = new SqlHelper(connectionString);
The code compiled alright. But I'm getting errors in the actual usage. One of the connections is diagnosed as active, while the second one produces a error.
Why question is.. can I reference two connection strings to a single sql helper class? If yes, any ideas where I might be making a mistake?
Update:
So this is the error that I am receiving. But if I restart the application and try the same connection first, I will be receiving a positive indicator.
My C# application uses Sql Server Compact Edition in which I got connections to the database here and there. I use this method to run ExecuteScalar and I use it repetitive in some point.
This is the class:
//_cnt & _cmd are private variables
public static object Run_ExecuteScaler(string query)
{
object objResult;
_cnt = new SqlCeConnection {ConnectionString = ConnectionString};
_cmd = new SqlCeCommand
{
Connection = _cnt,
CommandType = System.Data.CommandType.Text,
CommandText = query
};
if (_cnt.State != System.Data.ConnectionState.Open)
_cnt.Open();
objResult = _cmd.ExecuteScalar();
_cmd.Dispose();
if (_cnt.State != System.Data.ConnectionState.Closed)
_cnt.Close();
_cnt.Dispose();
return objResult;
}
I use this line in a foreach loop which uses the above method to ctreate a connection to the database and run the command. It then closes the connection and disposes it.
var middleCat = RSSql.Run_ExecuteScaler(string.Format(
"SELECT Implication FROM tblMiddleCategory where IDMiddleCategory='{0}'",someInt));
But I'm getting this error after second loop:
Too many sessions are open
I realize that this usually happens when a connection hasn't been disposed. but I do it in my method. So Am I doing it in a wrong way?
Update
I changed the method to use using statement as #Damien_The_Unbeliever offered:
public static object Run_ExecuteScaler(string query)
{
object objResult = null;
using (_cnt = new SqlCeConnection( ConnectionString))
{
_cmd = new SqlCeCommand
{
Connection = _cnt,
CommandType = System.Data.CommandType.Text,
CommandText = query
};
if (_cnt.State != System.Data.ConnectionState.Open)
_cnt.Open();
objResult = _cmd.ExecuteScalar();
}
return objResult;
}
But I'm still getting the same error.
hello am working on back up access database using C#, i have four groups which is access configuration , database selection, database backup and database restore.
so on data configuration i have data source textbox user id textbox and password textbox on database selection i have database combbox so that i can select one so i wrote this code
public partial class Form11 : Form
{
private OleDbConnection conn;
private OleDbCommand command;
private OleDbDataReader reader;
string ole = "";
string connectionString = "";
public Form11()
{
InitializeComponent();
}
private void BtnConnect_Click(object sender, EventArgs e)
{
try
{
conn.ConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;" +
#"Data Source = "+txtDataSource.Text+"; User Id="+txtUserId.Text+"; Password="+txtPassword.Text+"";
conn = new OleDbConnection(connectionString);
conn.Open();
ole = "EXEC sp_databases";
command = new OleDbCommand(ole, conn);
reader = command.ExecuteReader();
cmbDatabases.Items.Clear();
while (reader.Read())
{
cmbDatabases.Items.Add(reader[0].ToString());
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
the problem is i keep seeing object reference not set to an instance of an object, here i use access database but on SQL i didn't have such problem, please help me out with this thing.
thank you.
Conn is an object and is not instantiated yet when you are using conn.ConnectionString property
just flip the order this 2 lines
try
{
conn = new OleDbConnection();
conn.ConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;" +
#"Data Source = "+txtDataSource.Text+"; User Id="+txtUserId.Text+"; Password="+txtPassword.Text+"";
In your code, you are using your connection before instantiating your connection object. You need this first:
conn = new OleDbConnection();
The error should have referenced a line in your code that you were getting this problem - often relatively easy to track back from there to see what is null.
Im a beginner to C# (.net of course) and for my final year project im developing a payroll system. Now I have some issues regarding ado.net sql connection object.
To keep the connection string centrally I have used a separate class call db. Taking another step to this centralization thinking, I've initialized the connection object also centrally in this db class as follows.
class db
{
string connectionString = ("connection string will be here...");
public SqlConnection GetConn()
{
SqlConnection NewConn = new SqlConnection(connectionString);
return NewConn;
}
}
Now Im using this connection object as follows in my application...
I just want to know whether I would face issues in future because of this practice and also appreciate if one of experts could explain me what is the best practice in this regard.
Thanks in advance
class client
{
db NewDB = new db(); // db class is instantiated...
SqlConnection newCon; // object referece newConn is created...
//Method to insert new clients to 'client' table
public void addNewClient(DateTime entDate, client NewClient)
{
try
{
newCon = NewDB.GetConn(); // connection object is assigned to newCon... but this is optional and I put this for the clarity
string CommandString = "INSERT INTO client(Client_Name, C_Add, Contact_Person, C_Mob_No, C_Tel_No, Remarks, Ent_Date)" +
" VALUES (#CName, #CAdd, #CPerson, #CMob, #CTel, #Remarks, #entDate)";
SqlCommand SqlCom = new SqlCommand();
SqlCom.CommandText = CommandString;
SqlCom.Parameters.Add("#CName", SqlDbType.VarChar).Value = NewClient.CName;
SqlCom.Parameters.Add("#CAdd", SqlDbType.VarChar).Value = NewClient.CAdd;
SqlCom.Parameters.Add("#CPerson", SqlDbType.VarChar).Value = NewClient.CPerson;
SqlCom.Parameters.Add("#CMob", SqlDbType.Char).Value = NewClient.CMob;
SqlCom.Parameters.Add("#CTel", SqlDbType.Char).Value = NewClient.CTel;
SqlCom.Parameters.Add("#Remarks", SqlDbType.VarChar).Value = NewClient.Remarks;
SqlCom.Parameters.Add("#entDate", SqlDbType.Date).Value = entDate;
SqlCom.Connection = newCon;
newCon.Open();
SqlCom.ExecuteNonQuery();
}
catch
{
throw;
}
finally
{
newCon.Close(); // newCon object is global to entire class so can call its close method.
}
}
}
You don't need to use global connection object. Your db connections are stored in connection pool. So you won't run out of connections. Read more about connections pooling.
Looking at your client class it is bad practice to write raw SQl in the code. It is better practice to write a stored procedure and call it from the code passing the parameters.
public void addNewClient(DateTime entDate, client NewClient)
{
try
{
newCon = NewDB.GetConn(); // create connection
conn.Open(); //open connection
// create a command object identifying the stored procedure
SqlCommand SqlCom = new SqlCommand("Store Procedure name", newConn);
// add parameter to sql command, which is passed to the stored procedure
SqlCom .Parameters.Add(new SqlParameter("#CName", NewClient.CName));
// Rest of parameters
// execute the command
cmd.ExecuteReader();
}
}
Creating a class to store the connection is good practice. However you could expand on this further.
public struct slqParameters
{
public object ParamData { get; set; }
public string ParamKey { get; set; }
public SqlDbType ParamDatabaseType { get; set; }
public int ParamSize { get; set; }
}
class db
{
private string connectionString = ("connection string will be here...");
public static void ExecuteStoreProcedure(string ProcedureName, ref slqParameters[] CommandParameters)
{
string str_ConnectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
try
{
using (SqlConnection sqlConnection = new SqlConnection(str_ConnectionString))
{
using (SqlCommand sqlCommand = new SqlCommand(sProcedureName, sqlConnection) { CommandType = CommandType.StoredProcedure })
{
// Add all the parameters to the sql command.
foreach (slqParametersParameter in CommandParameters)
{
// Add a parameter
sqlCommand.Parameters.Add(new SqlParameter(Parameter.ParamKey, Parameter._ParamDatabaseType , Parameter._ParamSize ) { Value = Parameter.ParamData });
}
sqlConnection.Open();
DataTable dtTable = new DataTable();
sqlCommand.ExecuteReader())
}
}
}
catch (Exception error)
{
throw error;
}
}
}
This is only a ruff guide as i have not tested it yet but it should work
To use it on your page
Public SomeMethod()
{
slqParameters[] parameters = new Parameters[1]
{
new sqlParameters{ ParamData = , paramKey = "#CName", ParamDatabaseType = NewClient.CName}
};
db.ExecuteStoreProcedure("Store Procedure name", parameters);
}
I'm trying to implement a method that will provide the SqlConnection, how should I do it?
public class DAL
{
public bool dbCon()
{
string comboValue;
try
{
using (SqlConnection sqlConn =
new SqlConnection(#"Data Source =VirtualXP-64805;Initial Catalog=CTS_Demo;Integrated Security=SSPI"))
{
sqlConn.Open();
}
}
catch (SqlException Ex)
{
MessageBox.Show(Ex.ToString());
}
}
}
You method should return the connection object not a bool value, or you may define a class level connection variable and use that.
But When it comes to Database Connection then open it as late as possible and close it as early as possible
Instead of opening the connection from the method you may simply return the connection object and open it where you need it. Something like:
public SqlConnection dbCon()
{
return new SqlConnection(#"Data Source =VirtualXP-64805;Initial Catalog=CTS_Demo;Integrated Security=SSPI");
}
and then where you are using it:
using(SqlConnection conn = dbCon())
{
conn.Open();
.... your code
}
Or you can get rid of the method and simply call the new SqlConnection with connection string from the configuration.
EDIT:
Since you want to return an open connection from your method, you can do the following, but IMO its not the recommended way, you have to call Dispose manually for each connection object, since you will not use it within using statement.
public SqlConnection dbCon()
{
SqlConnection sqlConn;
try
{
sqlConn = new SqlConnection(#"Data Source =VirtualXP-64805;Initial Catalog=CTS_Demo;Integrated Security=SSPI")
}
catch(SqlException)
{
//your exception handling details
sqlConn = null;
}
return sqlConn;
}