I have a function of return type datatable
public DataTable GetAllPrimaryKeyTables(string ConnectionString)
{
// Create the datatable
DataTable dtListOfPrimaryKeyTables = new DataTable("tableNames");
// Query to select primary key tables.
string selectPrimaryKeyTables = #"SELECT
TABLE_NAME
AS
TABLES
FROM
INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE
CONSTRAINT_TYPE = 'PRIMARY KEY'
AND
TABLE_NAME <> 'dtProperties'
ORDER BY
TABLE_NAME";
// put your SqlConnection and SqlCommand into using blocks!
using(SqlConnection sConnection = new SqlConnection(ConnectionString))
using(SqlCommand sCommand = new SqlCommand(selectPrimaryKeyTables, sConnection))
{
try
{
// Create the dataadapter object
SqlDataAdapter sDataAdapter = new SqlDataAdapter(selectPrimaryKeyTables, sConnection);
// Fill the datatable - no need to open the connection, the SqlDataAdapter will do that all by itself
// (and also close it again after it is done)
sDataAdapter.Fill(dtListOfPrimaryKeyTables);
//using(StringWriter sw = new StringWriter())
//{
// dtListOfPrimaryKeyTables.WriteXml(sw);
// sw.WriteLine();
// result = sw.ToString();
//}
}
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);
}
}
// return the data table to the caller
return dtListOfPrimaryKeyTables;
}
And I am calling it like this...
public class PrimaryKeyChecker : IMFDBAnalyserPlugin
{
public DataTable RunAnalysis(string ConnectionString)
{
return GetAllPrimaryKeyTables(ConnectionString);
}
In the IMFDBAnalyserPlugin I have
namespace MFDBAnalyser
{
public interface IMFDBAnalyserPlugin
{
DataTable RunAnalysis(string ConnectionString);
}
and on the main project background I have
private void btnStartAnalysis_Click(object sender, EventArgs e)
{
SqlConnectionStringBuilder objConnectionString = new SqlConnectionStringBuilder();
objConnectionString.DataSource = txtHost.Text;
objConnectionString.UserID = txtUsername.Text;
objConnectionString.Password = txtPassword.Text;
string[] arrArgs = {objConnectionString.ConnectionString};
string assemblyName = "PrimaryKeyChecker.dll";
Assembly assembly = Assembly.LoadFrom(assemblyName);
Type local_type = assembly.GetType("PrimaryKeyChecker.PrimaryKeyChecker");
MethodInfo objMI = local_type.GetMethod("RunAnalysis");
ConstructorInfo ci = local_type.GetConstructor(Type.EmptyTypes);
object responder = ci.Invoke(null);
object response = objMI.Invoke(responder, arrArgs);
But when I debug, the response object is returning only the empty datatable as I am unable to give the datasource in the first function because it is not inheriting controls there...
Hope the question is partially clear to you guys.. It should give the list of all tables when debugged but it is not taking the datagrid dgResultView there to give it a datasource...
This has nothing to do with inheritance; it looks like you are catching and logging exceptions:
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);
}
I would start by looking there; most likely something is throwing, and telling you why... If I had to guess, it looks like maybe you are missing:
sConnection.Open();
The fact that anything is returned tells me it is just an exception.
Personally I would have just let an unanticipated exception bubble to the UI, and let the UI react by logging it and showing the appropriate #fail page.
Also, when possible, cast the plugin to the interface:
string assemblyName = "PrimaryKeyChecker.dll";
Assembly assembly = Assembly.LoadFrom(assemblyName);
Type local_type = assembly.GetType("PrimaryKeyChecker.PrimaryKeyChecker");
IMFDBAnalyserPlugin analyser =
(IMFDBAnalyserPlugin)Activator.CreateInstance(local_type);
DataTable response = analyser.RunAnalysis(objConnectionString.ConnectionString);
Related
First post here. I'm trying to create a website that fetches data from an Oracle database and returns some tables. I was able to connect my database fine and made a DataConnector that returns a list of CodeDesc objects. My main problem right now is simply displaying that data to the screen, preferably in the form of a drop down list but I'm using a GridView for now.
Here's my front end:
protected void Button1_Click(object sender, EventArgs e)
{
DataConnector dc = new DataConnector();
GridView2.DataSource = dc.getCodeTypes();
GridView2.DataBind();
}
When I click the button, nothing is generated and the debugger only says "Exception thrown: 'System.ArgumentException' in Oracle.DataAccess.dll" Any help would be appreciated. This is my first time doing web development and it's been a struggle to get even this far. I'm using Visual Studio 2015
Back End:
//Create datatable to get info from db & return results
public List<CodeDesc> getCodeTypes()
{
try
{
OracleConnection con = new OracleConnection(connString);
con.Open();
string query = "select id, descr from code_desc where code_type_id = 0";
// Create the OracleCommand
OracleCommand cmd = new OracleCommand();
cmd.Connection = con;
cmd.CommandType = CommandType.Text;
// Execute command, create OracleDataReader object
OracleDataReader reader = cmd.ExecuteReader();
List<CodeDesc> L = new List<CodeDesc>();
while (reader.Read())
{
CodeDesc c = new CodeDesc();
c.id = reader.GetInt32(0);
c.description = reader.GetString(1);
L.Add(c);
}
// Clean up
reader.Dispose();
cmd.Dispose();
con.Dispose();
System.Diagnostics.Debug.WriteLine(L);
return L;
}
catch (Exception ex)
{
// catch clause here...
}
}
CodeDesc:
public class CodeDesc
{
public int id { get; set; }
public string description { get; set; }
}
Any help would be great.
You never set the query string to the CommandText property of the OracleCommand. Of course this can only result in an exception when you try to execute your command.
Said that, remember that every disposable object should be enclosed in a using statement. This is very important in case of exceptions because the correct closing and disposing is executed automatically exiting from the using block
public List<CodeDesc> getCodeTypes()
{
try
{
List<CodeDesc> L = new List<CodeDesc>();
string query = "select id, descr from code_desc where code_type_id = 0";
using(OracleConnection con = new OracleConnection(connString))
using(OracleCommand cmd = new OracleCommand(query, con))
{
con.Open();
// Execute command, create OracleDataReader object
using(OracleDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
CodeDesc c = new CodeDesc();
c.id = reader.GetInt32(0);
c.description = reader.GetString(1);
L.Add(c);
}
}
}
System.Diagnostics.Debug.WriteLine(L);
return L;
}
I ran into a problem where passing a connection from a TableAdapter to some methods throws an exception stating the connectionstring isn't initialized. There are quite a few questions on SO with this exception but none were passing the connection and most were because the ConnectionString was null. Weird thing is I used MessageBox.Show(connection.ConnectionString); through out the chain of methods and I receive a valid connection string at every step. This is a somewhat complicated program that is in production but I will try to simplify the code for this question...
This is the postInventoryData method, which takes a DataGridView with inventory items and iterates through it posting them to the inventory. I use a TransactionScope to ensure the changes are safely rolled back in the event of an error. If an item is a kit(an item comprised of other items) I must iterate through those items and remove them from the inventory. The problem occurs when I check whether or not the item is a kit.
public bool postInventoryData(DataGridView dgv)
{
bool successful = true;
TestDataSetTableAdapters.inentoryTrxTableAdapter inventoryTrxAdapter =
new TestDataSetTableAdapters.inentoryTrxTableAdapter();
try
{
using (TransactionScope trxScope = new TransactionScope
(TransactionScopeOption.Required, new System.TimeSpan(0, 15, 0)))
{
MessageBox.Show(inventoryTrxAdapter.Connection.ConnectionString); // <-- Valid ConnectionString
inventoryTrxAdapter.OpenConnection();
for (int i = 0; i < dgv.Rows.Count; i++)
{
//parameter values
string departmentCode = dgv.Rows[i].Cells["Department_Code"].Value.ToString();
string machineCode = dgv.Rows[i].Cells["Machine_Code"].Value.ToString();
string operatorCode = dgv.Rows[i].Cells["Operator_Code"].Value.ToString();
string itemNumber = dgv.Rows[i].Cells["Item_Number"].Value.ToString();
double? qtyProduced = Convert.ToDouble(dgv.Rows[i].Cells["Quantity"].Value.ToString());
bool isKit =
businessLayer.isItemNumberKit
(inventoryTrxAdapter.Connection, itemNumber); // <-- CULPRIT!
// Inserts the item
dailyProductionInsertQty(
departmentCode,
machineCode,
operatorCode,
itemNumber,
isKit,
qtyProduced,
inventoryTrxAdapter,
trxScope);
}
inventoryTrxAdapter.CloseConnection();
trxScope.Complete();
}
}
catch (System.Exception ex)
{
successful = false;
MessageBox.Show(ex.ToString());
}
return successful;
}
The isItemNumberKit method
public bool isItemNumberKit(SqlConnection connection, string itemNumber)
{
bool contains;
MessageBox.Show(connection.ConnectionString); // <-- Valid ConnectionString
DataTable dt = getKit(connection, itemNumber); // <-- CULPRIT!
if (dt.Rows.Count > 0)
{
contains = true;
}
else
{
contains = false;
}
return contains;
}
The getKit method
public DataTable getKit(SqlConnection connection, string itemNumber)
{
DataTable dt = new DataTable();
SqlConnection myConnection = connection;
MessageBox.Show(myConnection.ConnectionString); // <-- Valid ConnectionString
SqlParameter paramItemNumber = new SqlParameter();
paramItemNumber.ParameterName = "#ItemNumber";
paramItemNumber.Value = itemNumber;
paramItemNumber.SqlDbType = System.Data.SqlDbType.VarChar;
try
{
using (myConnection)
{
string sql =
#"SELECT kits.Row_Id,
kits.Kit_Item_Number,
kits.Location_Code
FROM Inventory.dbo.Z_PV_Kits kits
WHERE kits.Kit_Item_Number=#ItemNumber";
//myConnection.Open();
using (SqlCommand myCommand = new SqlCommand(sql, myConnection))
{
myCommand.Parameters.Add(paramItemNumber);
SqlDataReader reader = myCommand.ExecuteReader();
dt.Load(reader);
}
}
}
catch (Exception ex)
{
dt = null;
MessageBox.Show(ex.ToString());
}
return dt;
}
When I execute postInventoryData the program throws an exception with the message, "The connectionstring property has not been initialized." with the line numbers pointing to isItemNumberKit and getKit. As you can see in the code above, I used a MessageBox.Show(connection.ConnectionString) throughout the process and each time I received a valid Connection string. I have created a workaround which stores a cached DataTable containing all the kit items I can run linq statements on. I am not in emergency mode or anything but I thought this to be weird and an opportunity for me to learn. Thanks in advance for any help!
It might be possible that you have 2 app.config files in your solution with 2 different connection strings.
OK, I figured it out and now when I think about it the answer was somewhat obvious. I always use using(){} blocks to ensure connections and similar objects are properly disposed and taken care of after they are used. The solution was to simply remove the using(myConnection){} block from the getKit method like this:
public DataTable getKit(SqlConnection connection, string itemNumber)
{
DataTable dt = new DataTable();
SqlConnection myConnection = connection;
MessageBox.Show(myConnection.ConnectionString);
SqlParameter paramItemNumber = new SqlParameter();
paramItemNumber.ParameterName = "#ItemNumber";
paramItemNumber.Value = itemNumber;
paramItemNumber.SqlDbType = System.Data.SqlDbType.VarChar;
try
{
string sql =
#"SELECT kits.Row_Id,
kits.Kit_Item_Number,
kits.Location_Code
FROM Inventory.dbo.Z_PV_Kits kits
WHERE kits.Kit_Item_Number=#ItemNumber
";
//myConnection.Open();
using (SqlCommand myCommand = new SqlCommand(sql, myConnection))
{
myCommand.Parameters.Add(paramItemNumber);
SqlDataReader reader = myCommand.ExecuteReader();
dt.Load(reader);
}
}
catch (Exception ex)
{
dt = null;
MessageBox.Show(ex.ToString());
}
return dt;
}
This will leave the connection intact but properly dispose of the command. Sorry for the long winded question with a short simple answer. Hope this might help someone someday.
In my WindowsCE / Compact Framework (.NET1.1) project, I need to create a new table in code. I thought I could do it this way:
if (! TableExists("table42"))
{
CreateTable42();
}
public static bool TableExists(string tableName)
{
try
{
using (SqlCeConnection sqlConn = new SqlCeConnection(#"Data Source=\my documents\Platypus.SDF"))
{
sqlConn.Open();
string qryStr = "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = ?";
SqlCeCommand cmd = new SqlCeCommand(qryStr, sqlConn);
cmd.Parameters[0].Value = tableName;
cmd.CommandType = CommandType.Text;
int retCount = (int)cmd.ExecuteScalar();
return retCount > 0;
}
}
catch (Exception ex)
{
MessageBox.Show("TableExists ex.Message == " + ex.Message);
MessageBox.Show("TableExists ex.ToString() == " + ex.ToString());
MessageBox.Show("TableExists ex.GetBaseException() == " + ex.GetBaseException());
return false;
}
}
...but the call to TableExists() fails; and shows me:
TableExists ex.Message ==
TableExists ex.ToString() == System.Data.SqlServerCe.SqlCeException at System.Data.SqlServerCe.SqlConnection.ProcessResults(Int32 hr) at ...at Open(boolean silent) ...
TableExists ex.GetBaseException() == [same as ex.ToString() above]
"Int32 hr" ... ??? What the Hec Ramsey is that?
As documented previously in these environs, I can't step through this projct, so I rely on those calls to MessageBox.Show().
The rest of the related code, if it may be of interest, is:
public static void CreateTable42()
{
try
{
using (SqlCeConnection con = new SqlCeConnection(#"Data Source=\my documents\Platypus.SDF"))
{
con.Open();
using (SqlCeCommand com = new SqlCeCommand(
"create table table42 (setting_id INT IDENTITY NOT NULL PRIMARY KEY, setting_name varchar(40) not null, setting_value(63) varchar not null)", con))
{
com.ExecuteNonQuery();
WriteSettingsVal("table42settingname","table42settingval");
}
}
}
catch (Exception ex)
{
MessageBox.Show("CreateTable42 " + ex.Message);
}
}
public static void WriteSettingsVal(string settingName, string settingVal)
{
using (SqlCeConnection sqlConn = new SqlCeConnection(#"Data Source=\my documents\Platypus.SDF"))
{
sqlConn.Open();
string dmlStr = "insert into tabld42 (setting_name, setting_value) values(?, ?)";
SqlCeCommand cmd = new SqlCeCommand(dmlStr, sqlConn);
cmd.CommandType = CommandType.Text;
cmd.Parameters[0].Value = settingName;
cmd.Parameters[1].Value = settingVal;
try
{
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
MessageBox.Show("WriteSettingsVal " + ex.Message);
}
}
}
UPDATE
Answer to Brad Rem's comment:
I don't think it's necessary to encase the param in quotes, as other working code is like:
cmd.Parameters.Add("#account_id", Dept.AccountID);
-and:
cmd.Parameters[0].Value = Dept.AccountID;
(it does it one way the first time when in a loop, and the other way thereafter (don't ask me why).
Anyway, just for grins, I did change the TableExists() parameter code from this:
cmd.Parameters[0].Value = tableName;
...to this:
cmd.Parameters.Add("#TABLE_NAME", tableName);
...but I still get the exact same result.
UPDATE 2
Here (http://msdn.microsoft.com/en-us/library/aa237891(v=SQL.80).aspx) I found this: "Caution You must specify the SQL Server CE provider string when you open a SQL Server CE database."
They give this example:
cn.ConnectionString = "Provider=Microsoft.SQLSERVER.OLEDB.CE.2.0; data source=\Northwind.sdf"
I'm not doing that; my conn str is:
using (SqlCeConnection sqlConn = new SqlCeConnection(#"Data Source=\my documents\CCRDB.SDF"))
Could that be my problem?
UPDATE 3
I took this gent's advice (http://www.codeproject.com/Answers/629613/Why-is-my-SQLServer-CE-code-failing?cmt=487657#answer1) and added a catch for SqlCeExcpetions so that it is now:
public static bool TableExists(string tableName)
{
try
{
using (SqlCeConnection sqlConn = new SqlCeConnection(#"Data Source=\my documents\CCRDB.SDF"))
{
sqlConn.Open();
string qryStr = "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = #TABLE_NAME";
SqlCeCommand cmd = new SqlCeCommand(qryStr, sqlConn);
cmd.Parameters.Add("#TABLE_NAME", tableName);
cmd.CommandType = CommandType.Text;
int retCount = (int)cmd.ExecuteScalar();
return retCount > 0;
}
}
catch (SqlCeException sqlceex)
{
MessageBox.Show("TableExists sqlceex.Message == " + sqlceex.Message);
MessageBox.Show("TableExists sqlceex.ToString() == " + sqlceex.ToString());
return false;
. . .
The SqlCeException message is: "There is a file sharing violation. A different process might be using the file [,,,,,]" then "...processresults ... open ... getinstance ..."
UPDATE 4
Trying to use ctacke's sample code, but: Is Transaction absolutely necessary? I had to change the code to the following for my scenario/milieu, and don't know what Transaction should be or how to build it:
public static bool TableExists(string tableName)
{
string sql = string.Format("SELECT COUNT(*) FROM information_schema.tables WHERE table_name = '{0}'", tableName);
try
{
using (SqlCeConnection sqlConn = new SqlCeConnection(#"Data Source=\my documents\HHSDB.SDF"))
{
SqlCeCommand command = new SqlCeCommand(sql, sqlConn);
//command.Transaction = CurrentTransaction as SqlCeTransaction;
command.Connection = sqlConn;
command.CommandText = sql;
int count = Convert.ToInt32(command.ExecuteScalar());
return (count > 0);
}
}
catch (SqlCeException sqlceex)
{
MessageBox.Show("TableExists sqlceex.Message == " + sqlceex.Message);
return false;
}
}
UPDATE 5
With this code, the err msg I get is, "An err msg is available for this exception but cannot be displayed because these messages are optional and are not currently insallted on this device. Please install ... NETCFv35.Messages.EN.cab"
UPDATE 6
All too typically, this legacy, ancient-technology project is giving me headaches. It seems that only one connection is allowed to be open at a time, and the app opens one from the outset; so, I have to use that connection. However, it is a DBConnection, not a SqlCeConnection, so I can't use this code:
using (SqlCeCommand com = new SqlCeCommand(
"create table hhs_settings (setting_id int identity (1,1) Primary key, setting_name varchar(40) not null, setting_value(63) varchar not null)", frmCentral.dbconn))
{
com.ExecuteNonQuery();
WriteSettingsVal("beltprinter", "ZebraQL220");
}
...because the already-open connection type passed as an arg to the SqlCeCommand constructor is DBCommand, not the expected/required SqlCeConneection.
The tentacles of this code are far too wide and entrenched to rip out by the roots and refactor to make it more sensible: a single tentative step in the foothills causes a raging avalanche on Everest.
For fun I'd try two things. First, replace the '?' parameter with a named parameter like '#tablename' and see if that changes things. Yes, I know '?' should work, but it's a confusing, ugly precedent and maybe since it's a system table it's wonky. Yes, it's a stretch, but worth a try just to know.
The second thing I'd do is something like this method from the SQLCE implementation of the OpenNETCF ORM:
public override bool TableExists(string tableName)
{
var connection = GetConnection(true);
try
{
using (var command = GetNewCommandObject())
{
command.Transaction = CurrentTransaction as SqlCeTransaction;
command.Connection = connection;
var sql = string.Format("SELECT COUNT(*) FROM information_schema.tables WHERE table_name = '{0}'", tableName);
command.CommandText = sql;
var count = Convert.ToInt32(command.ExecuteScalar());
return (count > 0);
}
}
finally
{
DoneWithConnection(connection, true);
}
}
Note that I didn't even bother parameterizing, largely because I doubt it will provide any perf benefit (queue the hordes whining about SQL injection). This way definitely works - we've got it deployed and in use in many live solutions.
EDIT
For completeness (though I'm not sure it adds to clarity).
protected virtual IDbConnection GetConnection(bool maintenance)
{
switch (ConnectionBehavior)
{
case ConnectionBehavior.AlwaysNew:
var connection = GetNewConnectionObject();
connection.Open();
return connection;
case ConnectionBehavior.HoldMaintenance:
if (m_connection == null)
{
m_connection = GetNewConnectionObject();
m_connection.Open();
}
if (maintenance) return m_connection;
var connection2 = GetNewConnectionObject();
connection2.Open();
return connection2;
case ConnectionBehavior.Persistent:
if (m_connection == null)
{
m_connection = GetNewConnectionObject();
m_connection.Open();
}
return m_connection;
default:
throw new NotSupportedException();
}
}
protected virtual void DoneWithConnection(IDbConnection connection, bool maintenance)
{
switch (ConnectionBehavior)
{
case ConnectionBehavior.AlwaysNew:
connection.Close();
connection.Dispose();
break;
case ConnectionBehavior.HoldMaintenance:
if (maintenance) return;
connection.Close();
connection.Dispose();
break;
case ConnectionBehavior.Persistent:
return;
default:
throw new NotSupportedException();
}
}
wow... still struggling... I did too when I first got started on a handheld device SQL-CE. My current project is running with C#.Net 3.5 but I think the principles you are running into are the same. Here is what is working for my system in it's close parallels to yours.
First, the connection string to the handheld. It is just
string myConnString = #"Data Source=\MyFolder\MyData.sdf";
no reference to the sql driver
Next, the TableExists
SqlCeCommand oCmd = new SqlCeCommand( "select * from INFORMATION_SCHEME.TABLES "
+ " where TABLE_NAME = #pTableName" );
oCmd.Parameters.Add( new SqlCeParameter( "pTableName", YourTableParameterToFunction ));
The "#pTableName" is to differentiate between the "TABLE_NAME" column and to absolutely prevent any issues about ambiguity. The Parameter does NOT get the extra "#". In SQL, the # indicates to look for a variable... The SqlCeParameter of "pTableName" must match as it is in the SQL Command (but without the leading "#").
Instead of issuing a call to ExecuteScalar, I am actually pulling the data down into a DataTable via
DataTable oTmpTbl = new DataTable();
SqlCeDataAdapter da = new SqlCeDataAdapter( oCmd );
da.Fill( oTmpTbl );
bool tblExists = oTbl.Rows.Count > 0;
This way, I either get records back or I dont... if I do, the number of records should be > 0. Since I'm not doing a "LIKE", it should only return the one in question.
When you get into your insert, updates and deletes, I have always tried to prefix my parameters with something like "#pWhateverColumn" and make sure the SqlCeParameter is by the same name but without the "#". I haven't had any issues and this project has been running for years. Yes it's a .net 3.5 app, but the fundamental basics of connecting and querying SHOULD be the same.
If it IS all within your application, I would try something like creating a single global static "Connection" object. Then, a single static method to handle it. Then, instead of doing a NEW connection during every "using" attempt, change it to something like...
public static class ConnectionHandler
{
static SqlCeConnection myGlobalConnection;
public static SqlCeConnection GetConnection()
{
if( myGlobalConnection == null )
myGlobalConnection = new SqlCeConnection();
return myGlobalConnection;
}
public static bool SqlConnect()
{
GetConnection(); // just to ensure object is created
if( myGlobalConnection.State != System.Data.ConnectionState.Open)
{
try
{
myGlobalConnection.ConnectionString = #"Data Source=\MyFolder\MyDatabase.sdf";
myGlobalConnection.Open();
}
catch( Exception ex)
{
// optionally messagebox, or preserve the connection error to the user
}
}
if( myGlobalConnection.State != System.Data.ConnectionState.Open )
MessageBox.Show( "notify user");
// return if it IS successful at opening the connection (or was already open)
return myGlobalConnection.State == System.Data.ConnectionState.Open;
}
public static void SqlDisconnect()
{
if (myGlobalConnection!= null)
{
if (myGlobalConnection.State == ConnectionState.Open)
myGlobalConnection.Close();
// In case some "other" state, always try to force CLOSE
// such as Connecting, Broken, Fetching, etc...
try
{ myGlobalConnection.Close(); }
catch
{ // notify user if issue}
}
}
}
... in your other class / function...
if( ConnectionHandler.SqlConnect() )
Using( SqlCeConnection conn = ConnectionHandler.GetConnection )
{
// do your stuff
}
... finally, when your app is finished, or any other time you need to...
ConnectionHandler.SqlDisconnect();
This keeps things centralized, and you don't have to worry about open/close, what the connection string is buried all over the place, etc... If you can't connect, you can't run a query, don't try to run the query if it can't even get that far.
I think it may be a permission issue on INFORMATION_SCHEMA system views. Try the following.
GRANT VIEW DEFINITION TO your_user;
See here for more details
I have a function like this
public void GetTablesWithUpperCaseName()
{
SqlConnectionStringBuilder objConnectionString = new SqlConnectionStringBuilder();
objConnectionString.DataSource = txtHost.Text;
objConnectionString.UserID = txtUsername.Text;
objConnectionString.Password = txtPassword.Text;
objConnectionString.InitialCatalog = Convert.ToString(cmbDatabases.SelectedValue);
SqlConnection sConnection = new SqlConnection(objConnectionString.ConnectionString);
//To Open the connection.
sConnection.Open();
//Query to select table_names that have their names in uppercase letters.
string selectTablesWithUppercaseName = #"SELECT
NAME
FROM
sysobjects
WHERE
UPPER(name) COLLATE Latin1_General_BIN = name COLLATE Latin1_General_BIN
AND
OBJECTPROPERTY(ID,N'IsTable')=1
AND
OBJECTPROPERTY(ID,N'IsMSShipped')=0 ";
//Create the command object
SqlCommand sCommand = new SqlCommand(selectTablesWithUppercaseName, sConnection);
try
{
//Create the dataset
DataSet dsListOfTablesWithUppercaseName = new DataSet("sysobjects");
//Create the dataadapter object
SqlDataAdapter sDataAdapter = new SqlDataAdapter(selectTablesWithUppercaseName, sConnection);
//Provides the master mapping between the sourcr table and system.data.datatable
sDataAdapter.TableMappings.Add("Table", "sysobjects");
//Fill the dataset
sDataAdapter.Fill(dsListOfTablesWithUppercaseName);
//Bind the result combobox with foreign key table names
DataViewManager dvmListOfForeignKeys = dsListOfTablesWithUppercaseName.DefaultViewManager;
dgResultView.DataSource = dsListOfTablesWithUppercaseName.Tables["sysobjects"];
}
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);
}
finally
{
//If connection is not closed then close the connection
if(sConnection.State != ConnectionState.Closed)
{
sConnection.Close();
}
}
}
And another function for counting the rows generated from the previous functions. But this function
Null Reference Exception or Object
reference not set to an instance of
object..
Can anyone help me in this... why it is catching error only for the functions above and working fine for all other similar functions.
private void UpdateLabelText()
{
SqlConnectionStringBuilder objConnectionString = new SqlConnectionStringBuilder();
objConnectionString.DataSource = txtHost.Text;
objConnectionString.UserID = txtUsername.Text;
objConnectionString.Password = txtPassword.Text;
objConnectionString.InitialCatalog = Convert.ToString(cmbDatabases.SelectedValue);
SqlConnection sConnection = new SqlConnection(objConnectionString.ConnectionString);
//To Open the connection.
sConnection.Open();
try
{
int SelectedCellTotal = 0;
int counter;
// Iterate through the SelectedCells collection and sum up the values.
for(counter = 0;counter < (dgResultView.SelectedCells.Count);counter++)
{
if(dgResultView.SelectedCells[counter].FormattedValueType == Type.GetType("System.String"))
{
string value = null;
// If the cell contains a value that has not been commited,
if(dgResultView.IsCurrentCellDirty == true)
{
value = dgResultView.SelectedCells[counter].EditedFormattedValue.ToString();
}
else
{
value = dgResultView.SelectedCells[counter].FormattedValue.ToString();
}
if(value != null)
{
// Ignore cells in the Description column.
if(dgResultView.SelectedCells[counter].ColumnIndex != dgResultView.Columns["TABLE_NAME"].Index)
{
if(value.Length != 0)
{
SelectedCellTotal += int.Parse(value);
}
}
}
}
}
// Set the labels to reflect the current state of the DataGridView.
lblDisplay.Text = "There are Total " + dgResultView.RowCount + cmbOperations.SelectedItem.ToString();
}
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);
}
finally
{
//If connection is not closed then close the connection
if(sConnection.State != ConnectionState.Closed)
{
sConnection.Close();
}
}
}
Also the lblDisplay.Text is not taking proper spaces.
Waiting for reply
OK, I don't really have an answer why you're getting a "null reference exception" - but a few points to throw in, nonetheless:
I would use sys.tables instead of sysobjects and having to specify what type of object to query for
ALWAYS put your disposable SqlConnection and SqlCommand into using(.....) { ...... } blocks. That way, you won't need any finally {..} blocks, and .NET will take care of properly disposing of those objects when they're no longer needed
why do you use a DataSet when you only have a single table inside?? That's just unnecessary overhead - use a DataTable instead!
don't open the SqlConnection that early - wait 'til the very last moment, open it, execute query, close it again right away
actually, when using the SqlDataAdapter, you don't need to open the SqlConnection yourself at all - the SqlDataAdapter will do that for you (and close it again after it is done reading the data)
do not mix the retrieval of the data from the database with the binding to the UI element - this is a very bad practice. From the GetTablesWithUpperCaseName method, you should return something (like a DataTable) to the caller (the UI) and let the UI handle the binding process
along the same lines: that method should not be grabbing stuff from UI elements (like text boxes) itself - pass in those values as method parameters, to get a cleaner code - one that you might actually be able to reuse in another project some day
This is how I think your first method ought to look like
public DataTable GetTablesWithUpperCaseName(string server, string database,
string username, string password)
{
// Create the datatable
DataTable dtListOfTablesWithUppercaseName = new DataTable("tableNames");
SqlConnectionStringBuilder objConnectionString = new SqlConnectionStringBuilder();
objConnectionString.DataSource = server;;
objConnectionString.UserID = username;
objConnectionString.Password = password;
objConnectionString.InitialCatalog = database;
// Define the Query against sys.tables - much easier and cleaner!
string selectTablesWithUppercaseName =
"SELECT NAME FROM sys.tables WHERE UPPER(name) COLLATE Latin1_General_BIN = name COLLATE Latin1_General_BIN AND is_msshipped = 0";
// put your SqlConnection and SqlCommand into using blocks!
using (SqlConnection sConnection = new SqlConnection(objConnectionString.ConnectionString))
using (SqlCommand sCommand = new SqlCommand(selectTablesWithUppercaseName, sConnection))
{
try
{
// Create the dataadapter object
SqlDataAdapter sDataAdapter = new SqlDataAdapter(selectTablesWithUppercaseName, sConnection);
// Fill the datatable - no need to open the connection, the SqlDataAdapter will do that all by itself
// (and also close it again after it is done)
sDataAdapter.Fill(dtListOfTablesWithUppercaseName);
}
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);
}
}
// return the data table to the caller
return dtListOfTablesWithUppercaseName;
}
I'm trying to implement a method which will take a given connection string and return an ArrayList containing the contents of a SQL view.
I've verified the validity of the connection string and the view itself. However I don't see what the problem is in the code below. In debug, when it runs the ExecuteReader method and then try to enter the while loop to iterate through the records in the view, it immediately bails because for some reason sqlReader.Read() doesn't.
public ArrayList GetEligibles(string sConnectionString)
{
string sSQLCommand = "SELECT field1, field2 FROM ViewEligible";
ArrayList alEligible = new ArrayList();
using (SqlConnection sConn = new SqlConnection(sConnectionString))
{
// Open connection.
sConn.Open();
// Define the command.
SqlCommand sCmd = new SqlCommand(sSQLCommand, sConn);
// Execute the reader.
SqlDataReader sqlReader = sCmd.ExecuteReader(CommandBehavior.CloseConnection);
// Loop through data reader to add items to the array.
while (sqlReader.Read())
{
EligibleClass Person = new EligibleClass();
Person.field1 = sqlReader["field1"].ToString();
Person.field2 = sqlReader["field2"].ToString();
alEligible.Add(Person);
}
// Call Close when done reading.
sqlReader.Close();
}
return alEligible;
}
Note, EligibleClass is just a class object representing one row of the view's results.
A couple of things I would check:
Is the connection string ok
Does the user in your connection string have access to the database/view
Can you access that database from the pc your at
Does the ViewEligable view exist
Does the view contain a field1 and field2 column.
Here one way you could possibly clean up that code somewhat (assuming you have .net 2.0)
public List<EligibleClass> GetEligibles(string sConnectionString)
{
List<EligibleClass> alEligible = null;
try
{
using (SqlConnection sConn = new SqlConnection(sConnectionString))
{
sConn.Open();
using (SqlCommand sCmd = new SqlCommand())
{
sCmd.Connection = sConn;
sCmd.CommandText = "SELECT field1, field2 FROM ViewEligible";
using (SqlDataReader sqlReader = sCmd.ExecuteReader())
{
while (sqlReader.Read())
{
EligibleClass Person = new EligibleClass();
Person.field1 = sqlReader.GetString(0);
Person.field2 = sqlReader.GetString(1);
if (alEligible == null) alEligible = new List<EligibleClass>();
alEligible.Add(Person);
}
}
}
}
}
catch (Exception ex)
{
// do something.
}
return alEligible;
}