I have this method, which I have in the base class that helps me to select anything from the children classes and also to reduce code repetition. The problem is when I call it I get an error which is a NullReferenceException (and when I look it up I find that the command in the method is empty).
This is the method in question:
This way I already know how to use but the other one I don't
SqlCommand command = new SqlCommand("select * from Customers where idCustomer=#idCustomer", OpenConnection());
command.Parameters.AddWithValue("#idCustomer", Id);
SqlDataReader reader = command.ExecuteReader();
Customer Onecustomer = null;
if (reader.Read())
{
Onecustomer = ReadCustomer(reader);
}
protected DataTable ExecuteSelectQuery(String query, params SqlParameter[] sqlParameters)
{
SqlCommand command = new SqlCommand();
DataTable dataTable;
DataSet dataSet = new DataSet();
try
{
command.Connection = OpenConnection();
command.CommandText = query;
command.Parameters.AddRange(sqlParameters);
command.ExecuteNonQuery();
adapter.SelectCommand = command;
adapter.Fill(dataSet);
dataTable = dataSet.Tables[0];
}
catch (SqlException e)
{
return null;
throw new Exception("Error :" + e.Message);
}
finally
{
CloseConnection();
}
return dataTable;
}
Here how I call it
string author = "Alfred Schmidt";
int id = 1;
// ExecuteEditQuery("UPDATE Books SET Title =#param1 WHERE idBook =#param2", sqlParameters);
//SqlParameter[] sqlParameters = new SqlParameter[1]
//{
// new SqlParameter ("#param1",author),
//};
SqlParameter[] myparm = new SqlParameter[1];
myparm[0] = new SqlParameter("#Author", SqlDbType.NVarChar, 200);
myparm[0].Value = author;
String query = #"SELECT * FROM Books WHERE Author =#Author";
DataTable dt = ExecuteSelectQuery(query, myparm);
for (int i = 0; i < dt.Rows.Count; i++)
{
Console.WriteLine(dt.Rows.ToString());
}
Console.Write("");
1
Is your OpenConnection() method returns a connection object. It may couse the error, the implementation of the method is not given. Also the adpater is not defined in the code, may be it can be the cause of error too, if it is not initialized.
And i want to say few things about your code:
1) You have and unnecessary command.ExecuteNonQuery(); statement in your ExecuteSelectQuery method.
2) DataAdapter can directly fill DataTable, you dont have to use DataSet.
Here's a proper rewrite of your method.
protected DataTable ExecuteSelectQuery(String query, params SqlParameter[] sqlParameters)
{
using (SqlCommand command = new SqlCommand())
try
{
command.CommandText = query;
command.Parameters.AddRange(sqlParameters);
command.Connection = OpenConnection();
DataTable dataTable = new DataTable();
using (SqlDataAdapter adapter = new SqlDataAdapter(command))
adapter.Fill(dataTable);
return dataTable;
}
catch (SqlException e)
{
return null;
throw new Exception("Error :" + e.Message);
}
finally
{
CloseConnection();
}
}
Note that the SqlDataAdapter can Open() and Close() the connection by itself, if the SqlConnection is Closed when Fill is called.
Related
I have this code running in form_load event:
using (SqlConnection sqlConn = new SqlConnection(strConn))
{
sqlConn.Open();
SqlDataAdapter sqlDa = new SqlDataAdapter("pp_sp_MachineAndOp", sqlConn);
DataTable sqlDt = Helper.ExecuteDataTable("pp_sp_MachineAndOp", new SqlParameter("#MachineAndOpID", 7));
sqlDa.Fill(sqlDt);
dgvMachineAndOp.AutoGenerateColumns = false;
dgvMachineAndOp.DataSource = sqlDt;
sqlDa.Dispose();
sqlConn.Close();
}
I get error 'Procedure or function 'pp_sp_MachineAndOp' expects parameter '#MachineAndOpID', which was not supplied.' at line:
sqlDa.Fill(sqlDt);
Important to say that if I open DataTable Visualizer of sqlDt at runtime I see expected results!
Here is a code behind Helper.ExecuteDataTable:
public static DataTable ExecuteDataTable(string storedProcedureName, params SqlParameter[] arrParam)
{
DataTable dt = new DataTable();
// Open the connection
using (SqlConnection sqlConn = new SqlConnection(strConn))
{
try
{
sqlConn.Open();
// Define the command
using (SqlCommand sqlCmd = new SqlCommand())
{
sqlCmd.Connection = sqlConn;
sqlCmd.CommandType = CommandType.StoredProcedure;
sqlCmd.CommandText = storedProcedureName;
// Handle the parameters
if (arrParam != null)
{
foreach (SqlParameter param in arrParam)
{
sqlCmd.Parameters.Add(param);
}
}
// Define the data adapter and fill the dataset
using (SqlDataAdapter da = new SqlDataAdapter(sqlCmd))
{
da.Fill(dt);
}
}
}
catch (SqlException ex)
{
MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
return dt;
}
What I am missing?
Remove everything except
DataTable sqlDt = Helper.ExecuteDataTable("pp_sp_MachineAndOp", new SqlParameter("#MachineAndOpID", 7));
dgvMachineAndOp.AutoGenerateColumns = false;
dgvMachineAndOp.DataSource = sqlDt;
your Helper.ExecuteDataTable is doing everything. you don't need to replicate same this in your code.
I think your helper class is creating connection with database as your data table has data.
So, try to remove stored proc name and connection object from adaptor and then check.
SqlDataAdapter sqlDa = new SqlDataAdapter();//use this only.
you can use below function(modification required as per your need):
public IDataReader ExecuteReader(string spName, object[] parameterValues)
{
command = GetCommand();
command.CommandType = CommandType.StoredProcedure;
command.CommandText = spName;
if (parameterValues != null)
{
for (int i = 0; i < parameterValues.Length; i++)
{
command.Parameters.Add(parameterValues[i]);
}
}
reader = command.ExecuteReader();
if (parameterValues != null)
command.Parameters.Clear();
return reader;
}
I've successfully built up my method to execute a select command. It is working fine. Then I change my code for SqlDataAdapter DA = new SqlDataAdapter();
I tried to pass SqlCommand as CommandType.Text in the parameters but I can not do it successfully. I get error. Is there any way if I can pass it as parameters. Please see my code.
Running code (aspx page code)
if ((!string.IsNullOrEmpty(user_login.Value)) && (!string.IsNullOrEmpty(user_pass.Value)))
{
// username & password logic
DataTable dt = new DataTable();
string strQuery = "SELECT 1 FROM TBL_USER_INFO WHERE USERNAME = #USERNAME AND PASSWORD = #PASSWORD";
SqlCommand cmd = new SqlCommand(strQuery);
cmd.Parameters.Add("#USERNAME", SqlDbType.VarChar).Value = user_login.Value.Trim();
cmd.Parameters.Add("#PASSWORD", SqlDbType.VarChar).Value = user_pass.Value.Trim();
DBConnection conn_ = new DBConnection();
dt = conn_.SelectData(cmd);
if (conn_.SQL_dt.Rows.Count > 0)
{
Response.Redirect("Home.aspx", false);
}
}
Successful connection class code
public DataTable SelectData(SqlCommand command)
{
try
{
conn.Open();
SqlDataAdapter DA = new SqlDataAdapter();
command.CommandType = CommandType.Text;
command.Connection = conn;
DA.SelectCommand = command;
DA.Fill(SQL_dt);
return SQL_dt;
}
catch (Exception ex)
{
return null;
}
finally
{
conn.Close();
}
}
How can I pass CommandType.Text as parameters for SqlDataAdapter?
Error code
public DataTable SelectData(SqlCommand command)
{
try
{
conn.Open();
SqlDataAdapter DA = new SqlDataAdapter(command.CommandType.ToString(), conn);
// command.CommandType = CommandType.Text;
// command.Connection = conn;
DA.SelectCommand = command;
DA.Fill(SQL_dt);
return SQL_dt;
}
catch (Exception ex)
{
return null;
}
finally
{
conn.Close();
}
}
I am getting this error:
System.InvalidOperationException: Fill: SelectCommand.Connection property has not been initialized.
at System.Data.Common.DbDataAdapter.GetConnection3(DbDataAdapter adapter, IDbCommand command, String method)...
public DataTable SelectData(string query)
{
DataTable dt = new DataTable();
using (SqlConnection con = new SqlConnection("Your Connection String here"))
{
con.Open();
using (SqlCommand cmd = con.CreateCommand())
{
cmd.CommandText = query;
cmd.CommandType = CommandType.Text;
using (SqlDataAdapter adp = new SqlDataAdapter(cmd))
{
adp.Fill(dt);
return dt;
}
}
}
}
To use:
SelectData("select * from yourTable");
Reds has the answer. Just to clean the code up a little bit...
public DataTable SelectData(string query)
{
using (var connection = new SqlConnection("myConnectionString"))
using (var command = new SqlCommand(query, connection))
using (var adapter = new SqlDataAdapter(command))
{
var dt = new DataTable();
connection.Open();
adapter.Fill(dt);
return dt;
}
}
Actually you should pass the connection object on SQLCommand.Hope it helped you
DBConnection conn_ = new DBConnection();
SqlCommand cmd = new SqlCommand(strQuery,conn_);
The error that you are getting is not related to CommandType.Text, it says you have initialised the connection property of of SelectCommand. Basically you should uncomment "command.Connection = conn;" to get rid of this error. If you still face any other issue , it is better to provide those details in the questions to provide accurate answer.
I'm writing a stored procedure that currently contains only a SELECT query. It will be expanded to do a number of other things, which is why it has to be a stored procedure, but for now, it is a simple query.
Something like this:
SELECT name, occupation, position
FROM jobs
WHERE ...
I'm looking to return the results of this query to be used in C#. I want to add it to a list so that I can bind it to a GridView component.
I don't know how to go about this, though. If I have to insert it into a list after returning all selected data, then that's alright, I just need to know how to properly return the data so that I can do that.
If I can return it in a format that can be popped right into a list, though, that would be ideal.
In stored procedure, you just need to write the select query like the below:
CREATE PROCEDURE TestProcedure
AS
BEGIN
SELECT ID, Name
FROM Test
END
On C# side, you can access using Reader, datatable, adapter.
Using adapter has just explained by Susanna Floora.
Using Reader:
SqlConnection connection = new SqlConnection(ConnectionString);
command = new SqlCommand("TestProcedure", connection);
command.CommandType = System.Data.CommandType.StoredProcedure;
connection.Open();
SqlDataReader reader = command.ExecuteReader();
List<Test> TestList = new List<Test>();
Test test = null;
while (reader.Read())
{
test = new Test();
test.ID = int.Parse(reader["ID"].ToString());
test.Name = reader["Name"].ToString();
TestList.Add(test);
}
gvGrid.DataSource = TestList;
gvGrid.DataBind();
Using dataTable:
SqlConnection connection = new SqlConnection(ConnectionString);
command = new SqlCommand("TestProcedure", connection);
command.CommandType = System.Data.CommandType.StoredProcedure;
connection.Open();
DataTable dt = new DataTable();
dt.Load(command.ExecuteReader());
gvGrid.DataSource = dt;
gvGrid.DataBind();
I hope it will help you. :)
SqlConnection connection = new SqlConnection(ConnectionString);
command = new SqlCommand("TestProcedure", connection);
command.CommandType = System.Data.CommandType.StoredProcedure;
connection.Open();
DataTable dt = new DataTable();
dt.Load(command.ExecuteReader());
gvGrid.DataSource = dt;
gvGrid.DataBind();
SqlConnection con = new SqlConnection("Data Source=DShp;Initial Catalog=abc;Integrated Security=True");
SqlDataAdapter da = new SqlDataAdapter("data", con);
da.SelectCommand.CommandType= CommandType.StoredProcedure;
DataSet ds=new DataSet();
da.Fill(ds, "data");
GridView1.DataSource = ds.Tables["data"];
GridView1.DataBind();
Passing Parameters in Stored Procedure and calling it in C# Code behind as shown below?
SqlConnection conn = new SqlConnection(func.internalConnection);
var cmd = new SqlCommand("usp_CustomerPortalOrderDetails", conn);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.Add("#CustomerId", SqlDbType.Int).Value = customerId;
cmd.Parameters.Add("#Qid", SqlDbType.VarChar).Value = qid;
conn.Open();
// Populate Production Panels
DataTable listCustomerJobDetails = new DataTable();
listCustomerJobDetails.Load(cmd.ExecuteReader());
conn.Close();
I had the same question, took me ages to find a simple solution.
Using ASP.NET MVC 5 and EF 6:
When you add a stored procedure to your .edmx model, the result of the stored procedure will be delivered via an auto-generated object called yourStoredProcName_result.
This _result object contains the attributes corresponding to the columns in the database that your stored procedure selected.
The _result class can be simply converted to a list:
yourStoredProcName_result.ToList()
// GET: api/GetStudent
public Response Get() {
return StoredProcedure.GetStudent();
}
public static Response GetStudent() {
using (var db = new dal()) {
var student = db.Database.SqlQuery<GetStudentVm>("GetStudent").ToList();
return new Response {
Sucess = true,
Message = student.Count() + " Student found",
Data = student
};
}
}
Building on some of the responds here, i'd like to add an alternative way. Creating a generic method using reflection, that can map any Stored Procedure response to a List. That is, a List of any type you wish, as long as the given type contains similarly named members to the Stored Procedure columns in the response.
Ideally, i'd probably use Dapper for this - but here goes:
private static SqlConnection getConnectionString() // Should be gotten from config in secure storage.
{
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
builder.DataSource = "it.hurts.when.IP";
builder.UserID = "someDBUser";
builder.Password = "someDBPassword";
builder.InitialCatalog = "someDB";
return new SqlConnection(builder.ConnectionString);
}
public static List<T> ExecuteSP<T>(string SPName, List<SqlParameter> Params)
{
try
{
DataTable dataTable = new DataTable();
using (SqlConnection Connection = getConnectionString())
{
// Open connection
Connection.Open();
// Create command from params / SP
SqlCommand cmd = new SqlCommand(SPName, Connection);
// Add parameters
cmd.Parameters.AddRange(Params.ToArray());
cmd.CommandType = CommandType.StoredProcedure;
// Make datatable for conversion
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dataTable);
da.Dispose();
// Close connection
Connection.Close();
}
// Convert to list of T
var retVal = ConvertToList<T>(dataTable);
return retVal;
}
catch (SqlException e)
{
Console.WriteLine("ConvertToList Exception: " + e.ToString());
return new List<T>();
}
}
/// <summary>
/// Converts datatable to List<someType> if possible.
/// </summary>
public static List<T> ConvertToList<T>(DataTable dt)
{
try // Necesarry unfotunately.
{
var columnNames = dt.Columns.Cast<DataColumn>()
.Select(c => c.ColumnName)
.ToList();
var properties = typeof(T).GetProperties();
return dt.AsEnumerable().Select(row =>
{
var objT = Activator.CreateInstance<T>();
foreach (var pro in properties)
{
if (columnNames.Contains(pro.Name))
{
if (row[pro.Name].GetType() == typeof(System.DBNull)) pro.SetValue(objT, null, null);
else pro.SetValue(objT, row[pro.Name], null);
}
}
return objT;
}).ToList();
}
catch (Exception e)
{
Console.WriteLine("Failed to write data to list. Often this occurs due to type errors (DBNull, nullables), changes in SP's used or wrongly formatted SP output.");
Console.WriteLine("ConvertToList Exception: " + e.ToString());
return new List<T>();
}
}
Gist: https://gist.github.com/Big-al/4c1ff3ed87b88570f8f6b62ee2216f9f
May be this will help:
Getting rows from DB:
public static DataRowCollection getAllUsers(string tableName)
{
DataSet set = new DataSet();
SqlCommand comm = new SqlCommand();
comm.Connection = DAL.DAL.conn;
comm.CommandType = CommandType.StoredProcedure;
comm.CommandText = "getAllUsers";
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = comm;
da.Fill(set,tableName);
DataRowCollection usersCollection = set.Tables[tableName].Rows;
return usersCollection;
}
Populating DataGridView from DataRowCollection :
public static void ShowAllUsers(DataGridView grdView,string table, params string[] fields)
{
DataRowCollection userSet = getAllUsers(table);
foreach (DataRow user in userSet)
{
grdView.Rows.Add(user[fields[0]],
user[fields[1]],
user[fields[2]],
user[fields[3]]);
}
}
Implementation :
BLL.BLL.ShowAllUsers(grdUsers,"eusers","eid","euname","eupassword","eposition");
I am using the below code to access the MS Access Database. But i got a error message Fill: SelectCommand.Connection property has not been initialized.How can i solve this issue.
common.cs
=========
public static bool DBConnectionStatus()
{
try
{
string conString = #"Provider=Microsoft.Jet.OLEDB.4.0; Data Source=|DataDirectory|db_admin.mdb; Jet OLEDB:Database Password=admin";
using (OleDbConnection conn = new OleDbConnection(conString))
{
conn.Open();
return (conn.State == ConnectionState.Open);
}
}
catch (OleDbException)
{
return false;
}
protected void btn_general_Click(object sender, EventArgs e)
{
try
{
bool state = common.DBConnectionStatus();
if (state == true)
{
cmd = new OleDbCommand("select * from tbl_admin");
da = new OleDbDataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds); // Error Here
if (ds.Tables[0].Rows.Count > 0)
{
}
}
}
catch (Exception e1)
{
}
}
I did suggest you to modify your code to something like this:
private DataTable YourData()
{
string conString = #"Provider=Microsoft.Jet.OLEDB.4.0; Data Source=|DataDirectory|db_admin.mdb; Jet OLEDB:Database Password=admin";
DataSet ds = new DataSet();
using (SqlConnection conn = new SqlConnection(conString))
{
try
{
conn.Open();
SqlCommand command = new SqlCommand("select * from tbl_admin", conn);
command.CommandType = CommandType.Text;
SqlDataAdapter adapter = new SqlDataAdapter(command);
adapter.Fill(ds);
if (ds.Tables[0].Rows.Count > 0)
{
// do somethign here
}
}
catch (Exception)
{
/*Handle error*/
}
}
return ds.Tables[0];
}
And then:
protected void btn_general_Click(object sender, EventArgs e)
{
this.YourData(); // you will get the Data here. you can then use it the way you want it
}
You are initializing a Command which you use to construct a DataAdapter, but both without setting the required Connection property:
cmd = new OleDbCommand("select * from tbl_admin"); // <-- no connectuion assigned
da = new OleDbDataAdapter(cmd); // <-- no connectuion assigned
So your exception is pretty self-explanatory.
One final note: using will dispose/close the connection, so the method DBConnectionStatus is pointless. So don't use it, instead use the using in in the first place:
try
{
using(var con = new OleDbConnection(connectionString))
using(var da = new OleDbDataAdapter("elect * from tbl_admin", con))
{
var table = new DataTable();
da.Fill(table); // note that you don't need to open the connection with DataAdapter.Fill
if (table.Rows.Count > 0)
{
// ...
}
}
}
catch (Exception e1)
{
// don't catch an exception if you don't handle it in a useful way(at least loggging)
throw;
}
As per your requirement you can also use SqlDataAdapter instand of ExecuteReader.
public void ReadMyData(string connectionString)
{
string queryString = "SELECT OrderID, CustomerID FROM Orders";
using (OleDbConnection connection = new OleDbConnection(connectionString))
{
OleDbCommand command = new OleDbCommand(queryString, connection);
connection.Open();
OleDbDataReader reader = command.ExecuteReader();
while (reader.Read())
{
Console.WriteLine(reader.GetInt32(0) + ", " + reader.GetString(1));
}
// always call Close when done reading.
reader.Close();
}
}
I am using system.data.common.dbcommand for database communications but I couldn't find ExecuteDataSet in it. Probably it is not supported. Please advice is there some way that I can read multiple datatable in one go (my stored procedure will return multiple selects).
Thanks
Loading data into a data-set is really the job of a data-adapter, so spin up an appropriate data-adapter and use that to load the data. You can also use dataSet.Load(reader).
However, please consider: are data-sets really the best metaphor for what you are doing?
public DataSet ExecuteDataSet(string procName,
params IDataParameter[] procParams)
{
SqlCommand cmd;
return ExecuteDataSet(out cmd, procName, procParams);
}
public DataSet ExecuteDataSet(out SqlCommand cmd, string procName,
params IDataParameter[] procParams)
{
SqlConnection cnx = null;
DataSet ds = new DataSet();
SqlDataAdapter da = new SqlDataAdapter();
cmd = null;
try
{
//Setup command object
cmd = new SqlCommand(procName);
cmd.CommandType = CommandType.StoredProcedure;
if (procParams != null)
{
for (int index = 0; index < procParams.Length; index++)
{
cmd.Parameters.Add(procParams[index]);
}
}
da.SelectCommand = (SqlCommand)cmd;
System.Diagnostics.Trace.Write(da.SelectCommand);
//Determine the transaction owner and process accordingly
if (_isOwner)
{
cnx = new SqlConnection(GetConnectionString());
cmd.Connection = cnx;
cnx.Open();
}
else
{
cmd.Connection = _txn.Connection;
cmd.Transaction = _txn;
}
//Fill the dataset
da.Fill(ds);
}
catch
{
throw;
}
finally
{
if (da != null) da.Dispose();
if (cmd != null) cmd.Dispose();
if (_isOwner)
{
cnx.Dispose(); //Implicitly calls cnx.Close()
}`enter code here`
}
return ds;
}