C# & SQL Unable to pull Data from Permissions Table - c#

I have a permissions database that I created which has 10 data points in it. I can insert data into this table through the program, but when I try to pull the data it's been giving me a lot of headaches. I've attempted to use a Using loop and it errors out every time, so I'm trying to just go super basic, and pull the data line by line but it's not working at all. My goal is to pull all the data into a List Variable so that I can call each individual permission later. What is stored in each permission is simply the Text True or False, with the exception of the first one Emp_ID being an Int.
Con is my connection script, and it's working perfectly, as it works everywhere else within the program.
Settings.Emp_ID is the Emp_ID of the user that's currently logged in. This means that we can skip the Emp_ID from the permissions when pulling the data, but I've attempted to do an EXCLUDE or SKIP but it's failed every time as well.
SQL Format, Emp_ID = INT, all others = Text
As for Error:
System.NullReference Exception 'Object Reference Not set to an instance of an object.
namespace TMS
{
public partial class Login_Form : Form
{
string[] Data;
void verify()
{
SqlDataReader rdr = null;
SqlCommand cmd = new SqlCommand("SELECT * FROM Permissions WHERE Emp_ID = '"
+ Settings.Emp_ID + "'", Con);
try
{
Con.Open();
rdr = cmd.ExecuteReader();
while (rdr.Read())
{
int Emp_ID = (int)rdr["Emp_ID"];
Data[0] = (string)rdr["Check_Out"];
Data[1] = (string)rdr["Check_In"];
Data[2] = (string)rdr["Self_His_Tool"];
Data[3] = (string)rdr["Self_His_User"];
Data[4] = (string)rdr["Tool_His"];
Data[5] = (string)rdr["User_His"];
Data[6] = (string)rdr["Add_Users"];
Data[7] = (string)rdr["Add_Tools"];
Data[8] = (string)rdr["Remove_Users"];
Data[9] = (string)rdr["Remove_Tools"];
}
}
finally
{
if (rdr != null)
{
rdr.Close();
}
if (Con != null)
Con.Close();
}
}

The Data array is still null, because this line does not actually create an array object:
string[] Data;
All it does is create a variable that might someday refer to an array object.
Later, when you have this and lines like it:
Data[0] = (string)rdr["Check_Out"];
You end up with the NullReferenceException. Data is still null, and so trying to access Data[0] is not allowed.
We want something more like this:
public class Permissions
{
//probably these should be "bool", but I adapted the types from the old code
public string Check_Out {get;set;}
public string Check_In {get;set;}
public string Self_His_Tool {get;set;}
public string Self_His_User {get;set;}
public string Tool_His {get;set;}
public string User_His {get;set;}
public string Add_Users {get;set;}
public string Add_Tools {get;set;}
public string Remove_Users {get;set;}
public string Remove_Tools {get;set;}
}
// ...
Permissions Data;
Permissions verify()
{
string SQL = "SELECT * FROM Permissions WHERE Emp_ID = #Emp_ID";
// Do NOT re-use the some connection object throughout an app or class!
// Only re-use the connection string.
// using directive will ensure connection is closed, so no need for finally block
using var con = new SqlConnection("connection string here");
using var cmd = new SqlCommand(SQL, con);
// Do NOT use string concatation to substitute data into a query!
cmd.Parameters.Add("#Emp_ID", SqlDbType.Int).Value = Settings.Emp_ID;
// don't need a "try" if there's no catch or finally
con.Open();
rdr = cmd.ExecuteReader();
Permissions result = null;
if (rdr.Read()) //Don't need "while" if we only expect one record
{
result = new Permissions();
int Emp_ID = Settings.Emp_ID;
result.Check_out =(string)rdr["Check_Out"];
result.Check_In = (string)rdr["Check_In"];
result.Self_His_Tool = (string)rdr["Self_His_Tool"];
result.Self_His_User = (string)rdr["Self_His_User"];
result.Tool_His = (string)rdr["Tool_His"];
result.User_His = (string)rdr["User_His"];
result.Add_Users = (string)rdr["Add_Users"];
result.Add_Tools = (string)rdr["Add_Tools"];
result.Remove_Users = (string)rdr["Remove_Users"];
result.Remove_Tools = (string)rdr["Remove_Tools"];
}
return result;
}

Related

Read multiple rows and multiple columns using SqlDataReader in C#

I need to know how I can get the values returned by multiple rows and multiple columns of a query using SqlDataReader in C#.
try
{
SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["conn"].ConnectionString);
connection.Open();
string query = ("select cardname,cardnumber,expiry,cardballance from vwallet where username='" + uname + "'");
SqlCommand cmd = new SqlCommand(query, connection);
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
//cardname = reader[0].ToString();
//cardnumber = reader[1].ToString();
//expiry = reader[2].ToString();
//cardballance = reader[3].ToString();
reader.
}
}
Note: I want to display the result returned by the query i.e cardnames, cardnumbers, expiry and cardballance into labels.
My current understanding is that the code I wrote will read only one row's column and assign to variables (declared already in the code, not pasted declaration here).
Data returned through table:
I want to display all of these in labels.
How to read all the data returned from table (table data shown in picture).
You are almost there. You just need an array or collection to store the rows in.
public class MyCard
{
public string Name { get; set; }
public string Number { get; set; }
public string Expiry { get; set; }
public string Balance { get; set; }
//Please note: This needs updating to match the data type used in your DB table.
//I have used string to show you a simple example.
}
Then update your code to include:
SqlDataReader reader = cmd.ExecuteReader();
List<MyCard> MyCardList = new List<MyCard>();
while (reader.Read())
{
MyCard mycard = new MyCard();
mycard.Name = reader[0].ToString();
mycard.Number = reader[1].ToString();
mycard.Expiry = reader[2].ToString();
mycard.Balance = reader[3].ToString();
MyCardList.Add(mycard);
}
//Remember to close the reader and dispose of objects correctly.
Then you have a list of MyCard objects with all your data.

object reference not set to an instance of an object, cannot figure out why

I quite new to c# and asp.net so plz tell me if i give you to little info for my question.
When a user is logging in I create an instance of my User object, calling my getcategories method and the redirect then user to another page. Like this:
if (dt.Rows.Count > 0){
user apa = new user();
apa.namn = dt.Rows[0]["FirstName"].ToString() + " " + dt.Rows[0]["LastName"].ToString();
apa.mail = dt.Rows[0]["Email"].ToString();
apa.id = dt.Rows[0]["ID"].ToString();
apa.firstname = dt.Rows[0]["FirstName"].ToString();
apa.lastnamn = dt.Rows[0]["LastName"].ToString();
apa.password = dt.Rows[0]["Password"].ToString();
Session["user"] = apa;
apa.getcategories();
Response.Redirect("visainlagg.aspx");
}
The problem is that I get "object reference not set to an instance of an object"-error on "kategorier[i].Name = dt.Rows[i]["Name"].ToString();" (the first thing that happens in my for loop in User class). I do not understand why :(
This is how the User class looks like:
public string namn;
public string mail;
public string id;
public string firstname;
public string lastname;
public string password;
public string constr = "secret";
public Post[] poster;
public anvcateg[] kategorier;
public int antalKategorier;
public void getcategories() {
SqlConnection conn = new SqlConnection();
conn.ConnectionString = constr;
SqlCommand com = new SqlCommand();
com.Connection = conn;
com.CommandText = "SELECT * FROM Category WHERE Author= '" + id + "'";
SqlDataAdapter adp = new SqlDataAdapter();
adp.SelectCommand = com;
DataTable dt = new DataTable();
adp.Fill(dt);
antalKategorier = dt.Rows.Count;
kategorier = new anvcateg[dt.Rows.Count];
for (int i = 0; i < dt.Rows.Count; i++)
{
kategorier[i].Name = dt.Rows[i]["Name"].ToString();
kategorier[i].ID = dt.Rows[i]["ID"].ToString();
kategorier[i].Description = dt.Rows[i]["Description"].ToString();
kategorier[i].Author = dt.Rows[i]["Author"].ToString();
}
}
the anvcateg class that getcategories() is using looks like this:
public class anvcateg
{
public string ID;
public string Name;
public string Description;
public string Author;
kategorier is an array of anvcateg
You initialized the array here:
kategorier = new anvcateg[dt.Rows.Count];
But you have to create an instance of anvcateg to add to your array)
for (int i = 0; i < dt.Rows.Count; i++)
{
kategorier[i] = new anvcateg()
{
ID = dt.Rows[i]["ID"].ToString(),
Author = dt.Rows[i]["Author"].ToString(),
Description = dt.Rows[i]["Description"].ToString(),
Name = dt.Rows[i]["Name"].ToString()
};
}
Your array contains all nulls - you have not created any objects. You have created an empty array. A quick fix would be:
kategorier[i] = new anvcateg();
at the start of each iteration.
For info, your current code is risky (SQL injection), doesn't clean up after itself, and unnecessarily complicated. Here's the same via "dapper":
using(var conn = new SqlConnection(constr)) {
conn.Open();
var data = conn.Query<anvcateg>(
"SELECT * FROM Category WHERE Author=#id",
new { id }).ToList();
}
(or ToArray() if you prefer)
This does all the mapping internally, cleans up the connection, and safely parameterises the "id" avoiding injection attacks. And no DataTable to be seen.
Your question is not quite clear, try to find the code "kategorier[i].Name = dt.Rows[i]["Name"].ToString();" but could not found it. if you can post your code which contain these lines then it would be easy to answer you.
Anyway, there may be the following reason of this error:
Either dt.Rows[i]["Name"] is null and you are trying to convert it into string by using .ToString(), change this to Convert.ToString(dt.Rows[i]["Name"])
check you have defined "kategorier" as an array or you can use the List kategorier = new List kategoriers();
Otherwise your code looks fine

oledb retrieve entire record and return from .accdb

example of a return function that returns only string value, how do I return multiple values consisting of different data types in a single record by simply calling one function?
public static string selectPassword(string user)
{
using (var connection = new OleDbConnection(connectionString))
using (var command = connection.CreateCommand())
{
command.Parameters.AddWithValue("#user", user);
command.CommandText = "SELECT [Password] FROM [Password_Table] WHERE Password_ID = [#user]";
command.CommandType = CommandType.Text;
connection.Open();
var value = command.ExecuteScalar();
return value == DBNull.Value ? null : value.ToString();
}
}
my record would be searched by Participant_Name, and would need to return Participant_Name, Participant_ID, Address, Contact_Number & Gender fields, all consisting of string, integers etc..
Create a data-type which consists of fields and properties that are able to hold the information that you want to retrieve.
Populate an instance of that type in your method, and return it.
Something like this, for instance:
public class Participant
{
public int Id { get; private set; }
public string Name {get; set;}
public string Address {get; set; }
public Participant( int id, string name, string address )
{
this.Id = id;
this.Name = name;
this.Address = address;
}
}
public Participant GetParticipant( string name )
{
using( var conn = new OleDbConnection (connectionString) )
{
using( var cmd = connection.CreateCommand() )
{
command.CommandText = "SELECT [Id], [Name], [Address] FROM Participant WHERE [name] LIKE #p_name";
command.Parameters.Add ("#p_name", OleDbType.VarChar).Value = name + "%";
using( var reader = command.ExecuteReader() )
{
if( !reader.HasRows() ) return null;
reader.Read();
return new Participant (reader.GetString("Id"), reader.GetString("name"), reader.GetString("address"));
}
}
}
}
Note: there can be syntax errors, since I haven't pulled it through the compiler, but I think you'll catch the drift.
for your needs you should return a DataRow object or an object array which you can get by calling .ItemArray on a DataRow
what you need to change in your method above is to use a DataAdapter and call its Fill method to fill a DataTable then return the first row of such DataTable, if any row is present.
you could also do this with the DataReader but then you should construct the array or objects container to return by yourself... I think dataRow.ItemArray is faster to code.

Filling custom C# objects from data received stored procedure

public class User
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Address
{
public string City { get; set; }
public string Country { get; set; }
}
/*
* There are 2 c# objects i have shown
* There is a stored procedure in my application which
* returns data for both objects simultaneously
* eg
* select FirstName, LasteName from Users where something="xyz"
* select City,Country from Locations where something="xyz"
*
* both queries are run by single procedure
* Now how can i fill both objects with from that stored procedure in asp.net using c#
*/
Use ADO.NET, open a SqlDataReader on a SqlCommand object executing the SP with the parameters. Use the SqlDataReader.NextResult method to get the second result set.
Basically:
SqlConnection cn = new SqlConnection("<ConnectionString>");
cn.Open();
SqlCommand Cmd = new SqlCommand("<StoredProcedureName>", cn);
Cmd.CommandType = System.Data.CommandType.StoredProcedure;
SqlDataReader dr = Cmd.ExecuteReader(CommandBehavior.CloseConnection);
while ( dr.Read() ) {
// populate your first object
}
dr.NextResult();
while ( dr.Read() ) {
// populate your second object
}
dr.Close();
You could use ADO.net and design a dataset which will create the classes for you so your queries will execute and read into classes which store the data you got.
http://msdn.microsoft.com/en-us/library/aa581776.aspx
That is an excellent tutorial on how to create a data access layer, which is what it sounds like you want to do.
using(SqlConnection connexion = new Sqlconnection(youconenctionstring))
using(SqlCommand command = conenxion.Createcommand())
{
command.Commandtext = "yourProcName";
command.CommandType = CommandType.StoredProcedure;
command.Paramters.Add("#yourparam",yourparamvalue);
connexion.Open();
SqlDataReader reader = command.ExecuteReader();
List<User> users = new List<User>;
List<Adress> adresses = new List<User>;
while(read.Read())
{
User user = new User();
user.firstName = (string) read["FirstName"];
users.Add(user);
}
read.NextResult();
while(read.Read)
{
Address address = new Address();
address.City = (string) read["Name"];
adresses.Add(address);
}
//make what you want with your both list
}
Linq to SQL, Entity Framework, or NHibernate would be my suggestions.
Check out the Enterprise library, specifically the Data Access block from microsoft patterns and practices. Even if you don't use it, you can steal, er... borrow code from it to do what you want.
http://www.codeplex.com/entlib

Using SqlDataReader to fill an ArrayList?

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;
}

Categories

Resources