I placed my DB reader in a separate class file because I didn't want to keep rewriting it but I keep getting the error:
Object reference not set to an instance of an object. db was null
This is my DataReader:
namespace ProjectName
{
public class DBReader
{
string dsn = ConfigurationManager.ConnectionStrings["database"].ConnectionString.ToString();
public SqlDataReader SqlReader(string sql, string retDebug = "")
{
try
{
SqlConnection conn;
SqlCommand cmd;
SqlDataReader dr_user;
conn = new SqlConnection(dsn);
conn.Open();
try
{
cmd = new SqlCommand(sql, conn);
cmd.CommandType = CommandType.Text;
cmd.CommandTimeout = 180;
dr_user = cmd.ExecuteReader(CommandBehavior.CloseConnection);
return dr_user;
}
catch (SqlException ex)
{
retDebug = ex.Message;
return null;
}
conn.Close();
conn.Dispose();
}
catch (Exception ex)
{
retDebug = ex.Message;
}
return null;
}
}
}
This is where I'm catching the error...at
SqlDataReader reader = db.SqlReader(query, "");
in the code shown here:
<!DOCTYPE html>
<script runat="server">
ProjectName.DBReader db;
string projectName;
protected void Page_Load(object sender, EventArgs e)
{
LoadProjects();
}
public void LoadProjects()
{
string query = #"SELECT * FROM projects where project_type = 3;
SqlDataReader reader = db.SqlReader(query, "");
while (reader.Read())
{
//code does something here
}
}
</script>
I want to be able to reuse this because I know I will be using it many times in this project.
Any help/direction would be appreciated!
As others pointed out, like any class, you have to create a instance of that class before using.
HOWEVER, if you don't have any public vars (at least ones that will change with different users on the web site), then you can also have public members of that class, and create the class as static. (but, those public members MUST be the same for all logged on users)
So, your choice.
Always create an instance of the class before using.
eg this:
public void LoadProjects()
{
string query = #"SELECT * FROM projects where project_type = 3";
DBReader MyDB = new DBReader();
SqlDataReader reader = MyDB.SqlReader(query, "");
while (reader.Read())
{
//code does something here
}
}
Or, you can declare the class as static, like this:
(air code warning).
public static class DBReader
{
static readonly string dsn = ConfigurationManager.ConnectionStrings["database"].ConnectionString.ToString();
static public SqlDataReader SqlReader(string sql, string retDebug = "")
{
SqlDataReader dr_user = null;
using (SqlConnection conn = new SqlConnection(dsn))
{
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.CommandType = CommandType.Text;
cmd.CommandTimeout = 180;
conn.Open();
dr_user = cmd.ExecuteReader();
}
}
return dr_user;
}
}
So, now in code you don't have to create a instance.
eg:
public void LoadProjects()
{
string query = #"SELECT * FROM projects where project_type = 3";
SqlDataReader reader = MyCode.DBReader.SqlReader(query, "");
while (reader.Read())
{
//code does something here
}
}
I'm first time for C#, Now I try to insert data to oracle db from variable. But I got this error. I don't know what point in this source code .
public class Foo
{
public string PLANTCODE { get; set; }
public string LOCATIONCODE { get; set; }
public string LOCATIONNAME { get; set; }
public string LOCATIONSTATUS { get; set; }
public string DEPARTMENTCODE { get; set; }
public string DEPARTMENTNAME { get; set; }
// public DateTime LASTUPDATED { get; set; }
// public OracleDbType OracleDbType { get; set; }
}
public List<Foo> GetData()
{
List<Foo> dataList = new List<Foo>();
string connectionString = "Data Source=xxx; Initial Catalog=xxx;Integrated Security = false; User ID=xxx;Password=xxx";
string selectStatement = "SELECT PLANTCODE,LOCATIONCODE,LOCATIONNAME,LOCATIONSTATUS,DEPARTMENTCODE,DEPARTMENTNAME from V_Location";
using (var con = new SqlConnection(connectionString))
{
using (var cmd = new SqlCommand(selectStatement, con))
{
con.Open();
using (var reader = cmd.ExecuteReader())
{ if (reader.Read())
{
dataList.Add(new Foo
{
PLANTCODE = reader.GetString(0),
LOCATIONCODE = reader.GetString(1),
LOCATIONNAME = reader.GetString(2),
LOCATIONSTATUS = reader.GetString(3),
DEPARTMENTCODE = reader.GetString(4),
DEPARTMENTNAME = reader.GetString(5),
});
}
}
}
}
return dataList;
}
public void InsertData()
{
string connectionString = "Provider=MSDAORA;Data Source=ORCL;Persist Security Info=True;User ID=xxx;Password=xxx;Unicode=True";
string insertStatment = "INSERT INTO xxx.BTH_V_LOCATION (PLANTCODE, LOCATIONCODE, LOCATIONNAME, LOCATIONSTATUS, DEPARTMENTCODE, DEPARTMENTNAME) VALUES (:PLANTCODE, :LOCATIONCODE, :LOCATIONNAME, :LOCATIONSTATUS, :DEPARTMENTCODE, :DEPARTMENTNAME)";
List<Foo> dataList = GetData();
if (dataList.Count > 0)
{
using (OleDbConnection con = new OleDbConnection(connectionString))
{
using (OleDbCommand cmd = new OleDbCommand(insertStatment, con))
{
con.Open();
foreach (var items in dataList)
{
cmd.Parameters.Clear();
cmd.Parameters.Add("PLANTCODE", OleDbType.VarChar).Value = items.PLANTCODE;
cmd.Parameters.Add("LOCATIONCODE", OleDbType.VarChar).Value = items.LOCATIONCODE;
cmd.Parameters.Add("LOCATIONNAME", OleDbType.VarChar).Value = items.LOCATIONNAME;
cmd.Parameters.Add("LOCATIONSTATUS", OleDbType.VarChar).Value = items.LOCATIONSTATUS;
cmd.Parameters.Add("DEPARTMENTCODE", OleDbType.VarChar).Value = items.DEPARTMENTCODE;
cmd.Parameters.Add("DEPARTMENTNAME", OleDbType.VarChar).Value = items.DEPARTMENTNAME;
}
cmd.ExecuteNonQuery();
}
}
}
}
private void button1_Click_1(object sender, EventArgs e)
{
InsertData();
}
}
}
This source code get select data from sql server first. After that keep data in variable for insert to oracle. Now I try to insert without variable then can insert data. but if I change to insert by variable but can't insert and get this error
ORA-01008: not all variables bound error" on "cmd.ExecuteNonQuery();
Move cmd.Parameters.clear(); outside the loop.
Seems to be clearing every time.
Thank you so much for your answer, But I try to move cmd.Parameters.clear(); , I still got same error.
using (OleDbConnection con = new OleDbConnection(connectionString)) //OleDbConnection
{
using (OleDbCommand cmd = new OleDbCommand(insertStatment, con)) //OleDbCommand
{
con.Open();
foreach (var items in dataList)
{
cmd.Parameters.Add("PLANTCODE", OleDbType.VarChar).Value = items.PLANTCODE;
cmd.Parameters.Add("LOCATIONCODE", OleDbType.VarChar).Value = items.LOCATIONCODE;
cmd.Parameters.Add("LOCATIONNAME", OleDbType.VarChar).Value = items.LOCATIONNAME;
cmd.Parameters.Add("LOCATIONSTATUS", OleDbType.VarChar).Value = items.LOCATIONSTATUS;
cmd.Parameters.Add("DEPARTMENTCODE", OleDbType.VarChar).Value = items.DEPARTMENTCODE;
cmd.Parameters.Add("DEPARTMENTNAME", OleDbType.VarChar).Value = items.DEPARTMENTNAME;
}
cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
}
}
and I try to swap "cmd.ExecuteNonQuery();" and "cmd.Parameters.Clear();" but same result.
Now I can fixed this problem, I change paramater name to "?"
string insertStatment = "INSERT INTO xxx.BTH_V_LOCATION (PLANTCODE, LOCATIONCODE, LOCATIONNAME, LOCATIONSTATUS, DEPARTMENTCODE, DEPARTMENTNAME) VALUES (?,?,?,?,?,?)";
List<Foo> dataList = GetData();
if (dataList.Count > 0)
{
using (OleDbConnection con2 = new OleDbConnection(connectionString)) //OleDbConnection
{
using (OleDbCommand cmd2 = new OleDbCommand(insertStatment, con2)) //OleDbCommand
{
con2.Open();
cmd2.Parameters.Clear();
foreach (var items in dataList)
{
cmd2.Parameters.Add("?", OleDbType.VarChar).Value = items.PLANTCODE;
cmd2.Parameters.Add("?", OleDbType.VarChar).Value = items.LOCATIONCODE;
cmd2.Parameters.Add("?", OleDbType.VarChar).Value = items.LOCATIONNAME;
cmd2.Parameters.Add("?", OleDbType.VarChar).Value = items.LOCATIONSTATUS;
cmd2.Parameters.Add("?", OleDbType.VarChar).Value = items.DEPARTMENTCODE;
cmd2.Parameters.Add("?", OleDbType.VarChar).Value = items.DEPARTMENTNAME;
//cmd2.ExecuteNonQuery();
//cmd2.Parameters.Clear();
}
cmd2.ExecuteNonQuery();
//cmd2.Parameters.Clear();
}
}
}
I think you need to use # instead of : for the parameters. And you need to execute within the loop and clear params after the execution.
string insertStatment = "INSERT INTO xxx.BTH_V_LOCATION (PLANTCODE, LOCATIONCODE, LOCATIONNAME, LOCATIONSTATUS, DEPARTMENTCODE, DEPARTMENTNAME) VALUES (#PLANTCODE, #LOCATIONCODE, #LOCATIONNAME, #LOCATIONSTATUS, #DEPARTMENTCODE, #DEPARTMENTNAME)";
List<Foo> dataList = GetData();
if (dataList.Count > 0)
{
using (OleDbConnection con = new OleDbConnection(connectionString))
{
using (OleDbCommand cmd = new OleDbCommand(insertStatment, con))
{
con.Open();
foreach (var items in dataList)
{
cmd.Parameters.AddRange(new OleDbParameter[]
{
new OleDbParameter("#PLANTCODE", items.PLANTCODE),
new OleDbParameter("#LOCATIONCODE", items.LOCATIONCODE),
new OleDbParameter("#LOCATIONNAME", items.LOCATIONNAME),
new OleDbParameter("#LOCATIONSTATUS", items.LOCATIONSTATUS),
new OleDbParameter("#DEPARTMENTCODE", items.DEPARTMENTCODE),
new OleDbParameter("#DEPARTMENTNAME", items.DEPARTMENTNAME),
});
cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
}
}
}
}
I'm trying to get two column details like this way:
public string GetData()
{
using (SqlConnection con = new SqlConnection(this.Connection))
{
con.Open();
SqlCommand command = new SqlCommand("Select TITTLE,VALUE from T_PROJECTS ", con);
// int result = command.ExecuteNonQuery();
using (SqlDataReader reader = command.ExecuteReader())
{
reader.Read();
return reader["TITTLE,VALUE"]?.ToString();
}
}
}
How can I do this?
You need to have a custom class of columns that you want to retrieve, for example,
public class Project
{
public int Title { get; set; }
public string Value { get; set; }
}
and then like this,
public Project GetData()
{
using (SqlConnection con = new SqlConnection(this.Connection))
{
con.Open();
SqlCommand command = new SqlCommand("Select TITTLE,VALUE from T_PROJECTS ", con);
Project proObj = new Project();
using (SqlDataReader reader = command.ExecuteReader())
{
reader.Read();
proObj.Title = reader["TITTLE"].ToString();
proObj.Value = reader["VALUE"].ToString();
}
}
return proObj;
}
You could also return a Tuple although I feel a custom class is a much better solution. -> https://msdn.microsoft.com/en-us/library/system.tuple(v=vs.110).aspx
public IEnumerable<Tuple<string,string>> GetData()
{
List<Tuple<string,string> results = new List<Tuple<string,string>>();
using (SqlConnection con = new SqlConnection(this.Connection))
{
con.Open();
SqlCommand command = new SqlCommand("Select TITTLE,VALUE from T_PROJECTS ", con);
using (SqlDataReader reader = command.ExecuteReader())
{
while(reader.Read())
results.add(new Tuple<string,string>(reader["TITLE"].ToString(),reader["VALUE"].ToString()));
}
return results;
}
}
Using this code I get my variable from an MS Access 2013 database and store it into a local variable:
public static int UpdateDBtCowsCalculatedVariable()
{
string StrCon = System.Configuration.ConfigurationManager.ConnectionStrings["FeedLibraryConnectionString"].ConnectionString;
OleDbConnection Connection = new OleDbConnection(StrCon);
OleDbCommand Cmd = new OleDbCommand();
Cmd.Connection = Connection;
Cmd.CommandText = "Select BW from tCows";
Connection.Open();
int BW = (int)Cmd.ExecuteScalar();
Connection.Close();
return BW;
}
But what about multiple variables? How should I do that?
I mean something like this:
public static void UpdateDBtCowsCalculatedVariable()
{
//int BW, DaysInMilk, AnimalType;
string StrCon = System.Configuration.ConfigurationManager.ConnectionStrings["FeedLibraryConnectionString"].ConnectionString;
OleDbConnection Connection = new OleDbConnection(StrCon);
OleDbCommand Cmd = new OleDbCommand();
Cmd.Connection = Connection;
Cmd.CommandText = "Select BW, DaysInMilk, AnimalType from tCows";
Connection.Open();
int BW = (int)Cmd.ExecuteScalar();
// int DaysInMilk = (int)Cmd.ExecuteScalar();
// int AnimalType = (int)Cmd.ExecuteScalar();
Connection.Close();
}
Why not ExecuteReader()? Even if you, technically, have just one record:
public static void UpdateDBtCowsCalculatedVariable()
{
string StrCon = ...
int BW = -1;
int DaysInMilk = -1;
int AnimalType = -1;
using (OleDbConnection Connection = new OleDbConnection(StrCon))
{
Connection.Open();
using (OleDbCommand Cmd = new OleDbCommand())
{
Cmd.Connection = Connection;
Cmd.CommandText =
#"select BW,
DaysInMilk,
AnimalType
from tCows";
using (var reader = Cmd.ExecuteReader())
{
if (reader.Read())
{
BW = Convert.ToInt32(reader.GetValue(0));
DaysInMilk = Convert.ToInt32(reader.GetValue(1));
AnimalType = Convert.ToInt32(reader.GetValue(2));
}
}
}
}
}
Try this:
public static void UpdateDBtCowsCalculatedVariable() {
//int BW, DaysInMilk, AnimalType;
string StrCon = System.Configuration.ConfigurationManager.ConnectionStrings["FeedLibraryConnectionString"].ConnectionString;
OleDbConnection Connection = new OleDbConnection(StrCon);
OleDbCommand Cmd = new OleDbCommand();
Cmd.Connection = Connection;
Cmd.CommandText = "Select BW, DaysInMilk, AnimalType from tCows";
Connection.Open();
reader = Cmd.ExecuteReader();
while (reader.Read())
{
int BW = reader.GetValue(0);
int DaysInMilk = reader.GetValue(1);
int AnimalType = reader.GetValue(2);
}
reader.Close();
Connection.Close();
}
I have written the following code to extract all records from the table in the SQL server. There is no error in the code but when I run it in fiddler, I am getting null objects.
[HttpGet]
public List<Student> Get()
{
SqlDataReader reader = null;
SqlConnection myConnection = new SqlConnection();
myConnection.ConnectionString = #"Data Source=PALLAVI-PC\SQLEXPRESS;Initial Catalog=StudentDB;Integrated Security=True;MultipleActiveResultSets=True;";
SqlCommand sqlCmd = new SqlCommand();
sqlCmd.CommandType = CommandType.Text;
sqlCmd.CommandText = "Select * from Tbl_Students;";
sqlCmd.Connection = myConnection;
myConnection.Open();
reader = sqlCmd.ExecuteReader();
int rowCount = 0;
while (reader.Read())
{
rowCount++;
}
Student[] student = new Student[rowCount];
for(int i=0;i<rowCount;i++)
{
student[i] = new Student();
}
int j = 0;
while (reader.Read())
{
// student[j] = new Student();
student[j].Roll_Number = Convert.ToInt32(reader.GetValue(0));
student[j].FirstName = reader.GetValue(1).ToString();
student[j].LastName = reader.GetValue(2).ToString();
student[j].Class = Convert.ToInt32(reader.GetValue(3));
student[j].Gender = reader.GetValue(4).ToString();
j++;
}
return student.ToList();
myConnection.Close();
}
I have 5 records in the table. I am able to get 5 json objects but without the content.
Attaching the image from Fiddler:
Student.cs
namespace WebAPIDemo.Models
{
public class Student
{
public int Roll_Number { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Class { get; set; }
public string Gender { get; set; }
}
}
Try this, without taking count of records. I'm not using the array, I have created new instance of student for each record.
public static List<Student> GetData()
{
List<Student> lstStudent = new List<Student>();
using (SqlConnection con = new SqlConnection(#"Data Source=PALLAVI-PC\SQLEXPRESS;Initial Catalog=StudentDB;Integrated Security=True;MultipleActiveResultSets=True;"))
{
using (SqlCommand cmd = new SqlCommand("Select * from Tbl_Students;", con))
{
cmd.CommandType = CommandType.Text;
if (con.State == ConnectionState.Closed)
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
while(reader.Read())
{
Student student =new Student();
student.Roll_Number = Convert.ToInt32(reader.GetValue(0));
student.FirstName = reader.GetValue(1).ToString();
student.LastName = reader.GetValue(2).ToString();
student.Class = Convert.ToInt32(reader.GetValue(3));
student.Gender = reader.GetValue(4).ToString();
lstStudent.Add(student);
}
}
}
return lstStudent;
}
your first while(reader.Read()) is the actual reader object with data. DataReader allows forward only read only access to a data row.The next while loop won't even execute because the Read() is already completed.So you're getting an array of 5 Student objects that are initialized with default values.
Instead of initializing an array of Student populate instances and add to a List<Student> inside the while loop.