This question already has answers here:
COM object that has been separated from its underlying RCW cannot be used. in oledb
(1 answer)
Hitting "COM object that has been separated from its underlying RCW cannot be used" error
(2 answers)
Closed 1 year ago.
My OleDB Class
public oleDB()
{
if (string.IsNullOrWhiteSpace(CONNECTION_STRING))
{
IDSTool.Security.EncryptDecryptData();
string dbname = "D:\\C# Desktop\\Database\\GoodsManagementMDB1.mdb;";
Source={0};Jet OLEDB:Database Password={1}", dbname, password);
CONNECTION_STRING = string.Format(#"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0}; Persist Security Info=False;", dbname);
ConnectionString = CONNECTION_STRING;
}
else
{
ConnectionString = CONNECTION_STRING;
}
DbConnection = new OleDbConnection(ConnectionString);
DbCommand = new OleDbCommand();
DbCommand.Connection = DbConnection;
}
public void ExecuteReader()
{
try
{
DbDataReader = DbCommand.ExecuteReader();
}
catch (Exception ex)
{
throw ex;
}
finally
{
DbCommand.Parameters.Clear();
}
}
My AbstractDataAccess
public IDbCommand DbCommand
{
get { return dbCommand; }
set { dbCommand = value; }
}
public void Close()
{
if (DbConnection.State == ConnectionState.Open || DbConnection.State == ConnectionState.Fetching)
DbConnection.Close();
}
#region IDisposable Members
public void Dispose()
{
dbConnection.Close();
dbConnection.Dispose();
dbCommand.Dispose();
if (dbDataReader != null)
{
dbDataReader.Close();
dbDataReader.Dispose();
}
if (dbDataAdapter != null)
{
dbDataAdapter = null;
}
GC.Collect();
GC.SuppressFinalize(this);
}
My User Class
public bool CheckLogin(string userID, string userpassword)
{
bool result = false;
using (DatabaseAccess.oleDB oleDB = new DatabaseAccess.oleDB())
{
using (oleDB.DbCommand)
{
oleDB.CommandText = #"SELECT * FROM[User] where UserID=#UserID";
oleDB.AddParameter("#UserID", System.Data.OleDb.OleDbType.VarChar, userID);
oleDB.CommandType = System.Data.CommandType.Text;
try
{
oleDB.Open();
oleDB.ExecuteReader();
while (oleDB.DbDataReader.Read())
{
if (userID == oleDB.DbDataReader["UserID"].ToString() && userpassword == Tools.Security.Decrypted(oleDB.DbDataReader["Password"].ToString()))
result = true;
else
result = false;
}
oleDB.Close();
return result;
}
catch (Exception)
{
return result;
throw;
}
}
}
}
I use the oledb class as a reference in the User class to connect to the access database, oledb inherits from the AbstratDataAccess class where the AbstratDataAccess class has properties dbconnection, dbcommand etc., I have declared new DbCommand in the oledb class, but why when DbCommand.Dispose(); in Public Void Closer() method an error appears COM object that has been separated from its underlying RCW cannot be used.
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";
}
}
I copied the ConnectString value from the properties of my local database.
Connection String from the properties is :
Data Source=Cyber\SQLEXPRESS;Initial Catalog=GeneratedData;Integrated Security=True;
When I directly copy the ConnectionString into ConnectString, I get an error. So I take that "\" off and I did not get an error. However it still does not work. I also noticed that people usually change that ConnectionString value to a single word to make it easy.However, my VB properties section is not allowing me to change it. Here is the error I get
public class SQLConnection
{
#region MemberVariables
private SqlConnection mConnection = null;
private SqlDataAdapter mDataAdapter = null;
private SqlCommand mCommand = null;
static string mDbConnString = string.Empty;
#endregion
#region PublicMemberVariables
public SqlConnection Connection
{
get
{
return mConnection;
}
set
{
mConnection = value;
}
}
public SqlDataAdapter DataAdapter
{
get
{
return mDataAdapter;
}
set
{
mDataAdapter = value;
}
}
public SqlCommand Command
{
get
{
return mCommand;
}
set
{
mCommand = value;
}
}
public string ConnectString
{
get
{
return mDbConnString;
}
set
{
lock (mDbConnString)
{
mDbConnString = value;
}
lock (mConnection)
{
mConnection.ConnectionString = mDbConnString;
}
}
}
#endregion
public void TestConnection()
{
ConnectString = "Data Source=Cyber SQLEXPRESS;Initial Catalog=GeneratedData;Integrated Security=True";
Connection = new SqlConnection(ConnectString);
Connection.Open();
MessageBox.Show(Connection.State.ToString());
}
}
Change
Data Source=Cyber\SQLEXPRESS;Initial Catalog=GeneratedData;Integrated Security=True;
To
Data Source=Cyber\\SQLEXPRESS;Initial Catalog=GeneratedData;Integrated Security=True;
How do i call the Businesslayer that is in the bin folder as a DLL. 'BusinessLogic' is my dll.
namespace BusinessLogic
{
public class BizLogic
{
string DbConnString = DbConnectionStrings.GetDbConnectionString();
public Dataset SignIn(string Username, string Password)
{
string strReturn = string.Empty;
DataSet pds = new DataSet();
try
{
SqlParameter[] parameters = new SqlParameter[]
{
new SqlParameter("#UserName", UserName )
,new SqlParameter("#Password", Password )
};
SqlHelper.FillDataset(DbConnString, System.Data.CommandType.StoredProcedure, "RepSignIn", pds, new string[] { "SignIn" }, parameters);
return pds;
}
catch (Exception ex)
{
return null;
}
}
}
}
The below part of the code used to work earlier but i changed the database from SQl 2008 R2 Express to 2008 R2 Web Edition with Windows Authentication, it stopped working. I cannot debug because its a DLL and when i have the Quickwatch on BusinssLogic, i see an error " BusinessLogic 'BusinessLogic' is a 'namespace', which is not valid in the given context
". This is in VS 2008.
DataSet ds = new BusinessLogic.BizLogic().SignIn(string Username, string Password);
Can someone please help me what is that i am missing. The connectionString in Web.config is like this
namespace BusinessLogic
{
public class DbConnectionStrings
{
private const string dbConnectionString = "ConnectionString";
public static string GetDbConnectionString()
{
return GetConnectionStringFromConfigFile(dbConnectionString);
}
private static string GetConnectionStringFromConfigFile(string ConnectionName)
{
string connstring = string.Empty;
try
{
connstring = System.Configuration.ConfigurationSettings.AppSettings[ConnectionName];
}
catch
{
}
return connstring;
}
public DbConnectionStrings()
{
}
}
}
Please let me know if you need to know anything else to guide me!
Thank you very much in advance!
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()
{
}
}