Retrieve Data From DataTable - c#

I am running a SQL Query which will return a count the query is
Select Count(numstudents) from classA
I am using C# to connect to SQL Server and execute this query, but my issue is, how do I get the actual number returned? My current method returns the number of rows in the DataTable which by default will always be 1. I need to get the Count() returned.
Here is full C# syntax:
private void GetData()
{
DataSet ds = new DataSet()
using (var con = new SqlConnection(connectionString))
{
using (var cmd = new SqlCommand("RunAStoredProc", con))
{
using (var da = new SqlDataAdapter(cmd))
{
cmd.CommandType = CommandType.StoredProcedure;
da.Fill(ds);
}
}
}
DataTable table1 = new DataTable();
table1 = ds.Tables[0];
DataTable table2 = new DataTable();
table2 = ds.Tables[1];
string numberreturned = table1.Rows.Count.ToString();
Console.WriteLine(numberreturned);
Console.ReadKey();
}
Stored procedure reads like such:
Alter Procedure [dbo].[GetData]
As
Select Count(*) FROM classA
Select studentfirstname, studentlastname FROM classA
Where enrolled = 'Yes'

You don't need an SqlDataAdapter and all the infrastructure required to work with if you just have a single value returned by your Stored Procedure. Just use ExecuteScalar
int count = 0;
using (var con = new SqlConnection(connectionString))
using (var cmd = new SqlCommand("RunAStoredProc", con))
{
cmd.CommandType = CommandType.StoredProcedure;
count = (int)cmd.ExecuteScalar();
}
Console.WriteLine(count);
Console.ReadKey();
However if your really want to use an adapter and a dataset then you can find the result of your query reading the value from the first row and first column from the returned table
int count = Convert.ToInt32(table1.Rows[0][0]);
or even (without declaring the table1 variable)
int count = Convert.ToInt32(ds.Tables[0].Rows[0][0]);
To discover the difference between the result of the first select statement and the count of rows returned in the second select statement you could write
int allStudents = Convert.ToInt32(ds.Tables[0].Rows[0][0]);
int enrolledStudents = ds.Tables[1].Rows.Count;
int notEnrolledStudents = allStudents - enrolledStudents;

Related

Table-Valued parameter IN clause pulling entire table not just values that passed

I have created Table-Valued parameter to use in IN clause. Looks like everything is perfect for I am getting entire table ids rather what I passed in IN clause. I passed 6 ids but return I got
120K ids.
Let know where I am making wrong.
CREATE TYPE StringsList as Table (Id varchar(100));
C#
MemberNumbers = "3229622,4183229,3257553,3003673,3358312,0682773";
string[] memberIds = MemberNumbers.Split(',');
public void GetMemberInfoAndMemberSubscriptionsUsingSP(string[] ids, ref string errMsg)
{
var result = new List<subscriptionExt>();
string connectionString = ConfigurationManager.AppSettings["personifyConn"];
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
using (SqlCommand command = new SqlCommand("GetMemberInfoAndMemberSubscriptions", conn))
{
command.CommandType = System.Data.CommandType.StoredProcedure;
var dt = new DataTable();
dt.Columns.Add("Id", typeof(string));
foreach (var id in ids)
{
dt.Rows.Add(id);
}
var parameter = command.Parameters.AddWithValue("ListIds", dt);
parameter.SqlDbType = SqlDbType.Structured;
var reader = command.ExecuteReader();
}
}
}
SQL
CREATE OR ALTER PROCEDURE [dbo].[GetMemberInfoAndMemberSubscriptions] ( #ListIds StringsList READONLY)
AS
BEGIN
SELECT [MASTER_CUSTOMER_ID], USR_SPE_Membership_Status
FROM CUSTOMER WHERE [MASTER_CUSTOMER_ID]
IN (SELECT [MASTER_CUSTOMER_ID] FROM #ListIds)
END
I don't anything wrong here.
#ListIds do not have the column MASTER_CUSTOMER_ID. In Subquery it should be Id instead of MASTER_CUSTOMER_ID.
SELECT [MASTER_CUSTOMER_ID], USR_SPE_Membership_Status
FROM CUSTOMER WHERE [MASTER_CUSTOMER_ID]
IN (SELECT ID FROM #ListIds)

Limiting the number of retrieved rows using Fill in ADOMD

The following C# code runs a DAX statement and retrieves a DataTable. This works fine, but now I need to retrieve from the database up to N rows. Is there a way to limit the number of rows returned by the Fill function? If not, how can I retrieve the top N rows? Note that I need to keep this generic for any DAX statement, so you shouldn't change the DAX itself. Also, I don't want to retrieve all the data and then take the first N rows as the data may be too large.
public static DataTable runDaxStatement(int maxRows) {
var con = ConfigurationManager.ConnectionStrings["Default"].ConnectionString;
AdomdConnection conn = new AdomdConnection(con);
DataSet ds = new DataSet();
ds.EnforceConstraints = false;
AdomdCommand cmd = new AdomdCommand("evaluate customers", conn);
AdomdDataAdapter da = new AdomdDataAdapter(cmd);
da.Fill(ds);
return ds.Tables[0];
}
Came across the following TOPN function in the documentation.
This can be used to return the top N rows of the specified table.
For example
public static DataTable runDaxStatement(int maxRows) {
var connectionString = ConfigurationManager.ConnectionStrings["Default"].ConnectionString;
using(AdomdConnection connection = new AdomdConnection(connectionString)) {
string commandText = $"EVALUATE TOPN({maxRows}, customers, <orderBy_expression_here>)";
AdomdCommand command = connection.CreateCommand();
command.CommandText = commandText;
DataSet dataSet = new DataSet(){
EnforceConstraints = false
}
AdomdDataAdapter adapter = new AdomdDataAdapter(command);
adapter.Fill(dataSet);
return dataSet.Tables[0];
}
}

is there is a way to print the database query result using SQLConnection

I am creating a SQLConnection to access some data. I need to print the entire DB result in log
I can able to print the specific cell value by referring out the cell, but I want to print the query result at single shot
string queryString = "select top 1 column_1, column_2 from master_table";
using (SqlConnection dbConnection = new SqlConnection(envDBConnectionString))
{
SqlCommand dbCommand = new SqlCommand(queryString, dbConnection);
dbConnection.Open();
SqlDataReader dbReader = dbCommand.ExecuteReader();
if (dbReader.HasRows)
{
while (dbReader.Read())
{
string col1Value = dbReader.GetValue(0).ToString());
string col2Value = dbReader.GetValue(1).ToString());
}
}
dbReader.Close();
dbConnection.Close();
}
Here I am getting each column value and stores it to string variable. instead I want to store the entire query result in that string
I suggest method extracting, i.e.
// Given a query, return records
private static IEnumerable<IDataRecord> QueryLines(string query) {
using (SqlConnection con = new SqlConnection(envDBConnectionString)) {
con.Open();
using (var q = new SqlCommand(query, con)) {
using (var reader = q.ExecuteReader()) {
while (reader.Read())
yield return reader as IDataRecord;
}
}
}
}
Then we can easily use it:
string command =
#"select top 1
column_1 as Column1,
column_2 as Column2
from master_table";
Having records, write them into a log in a desired format, e.g. simple CSV
File.AppendAllLines(#"c:\MyLog.txt", QueryLines(command)
.Select(record => $"{record[0]},{record[1]}"));
Or in elaborated XML
File.AppendAllLines(#"c:\MyLog.txt", QueryLines(command)
.Select(record => string.Concat(Enumerable
.Range(0, record.FieldCount)
.Select(i => $"<{record.GetName(i)}>{record[i]}</{record.GetName(i)}>")));
string queryString = "select top 1 column_1, column_2 from master_table";
using (SqlConnection dbConnection = new SqlConnection(envDBConnectionString))
{
SqlCommand dbCommand = new SqlCommand(queryString, dbConnection);
SqlDataAdapter sa = new SqlDataAdapter(dbCommand);
DataTable dt = new DataTable(); //All your data in this datatable
sa.fill(dt);
}
for reference:
Inside loop:
foreach(DataRow row in dt.rows){
row["COLUMN_NAME"].toString(); //or whatever datatype
}

C# reading values from datatable filled with sql select

I am coding win form app, which checks on startup right of the currently logged user. I had these right saved in MS SQL server in the table. When importing data to Datatable, there is no problem. But when I want to read value, there is message "cannot find column xy".
SqlDataAdapter sdaRights = new SqlDataAdapter("SELECT * FROM rights WHERE [user]='" + System.Security.Principal.WindowsIdentity.GetCurrent().Name + "'", conn);
DataTable dtRights = new DataTable(); //this is creating a virtual table
sdaRights.Fill(dtRights);
Object cellValue = dt.Rows[0][1];
int value = Convert.ToInt32(cellValue);
MessageBox.Show(value.ToString());
I would like, that program would save the value from SQL to int.
You are assuming that you have rows being returned, would be my first guess. You should loop through your DataTable instead of simply trying to access element 0 in it.
DataTable dtRights = new DataTable();
sdaRights.Fill(dtRights);
foreach(DataRow row in dtRights.Rows) {
Object cellValue = row[1];
int value = Convert.ToInt32(cellValue);
MessageBox.Show(value.ToString());
}
using (SqlConnection con = new SqlConnection("your connection string"))
{
using (SqlCommand cmd = new SqlCommand("SELECT [column_you_want] FROM [rights] WHERE [user] = #user"))
{
cmd.Parameters.AddWithValue("#user", System.Security.Principal.WindowsIdentity.GetCurrent().Name);
con.Open();
int right = Convert.ToInt32(cmd.ExecuteScalar());
}
}

How to create sql connection with c# code behind, access the sql server then conditionally redirect?

This is a question from an experienced beginner!
Using ASP.NET 4 C# AND SQL server,
I have a connection string in web.config to myDatabase named "myCS".
I have a database named myDB.
I have a table named myTable with a primary key named myPK
What are the NECESSARY lines of code behind (minimal code) to create a SQL connection, then select from myTable where myPK=="simpleText"
it will probably include:
sqlconnection conn = new sqlconnection(??? myCS)
string SQLcommand = select * from myDB.myTable where myPK==myTestString;
sqlCommand command = new SqlCommand(SQL,conn);
conn.Open();
booleanFlag = ????
conn.Close();
conn.Dispose();
then
If ( theAnswer != NULL ) // or (if flag)
{
Response.Redirect("Page1.aspx");
}
else
{
Response.Redirect("Page2.aspx");
}
Here is a limited simple tutorial:
First, you want to have a class to do the hard work for you, then you will use it with ease.
First, you have to crate the connection string in your web.config file and name it.
Here it is named DatabaseConnectionString, but you may named it myCS as required in the question.
Now, in App_Code create a new class file and name it SqlComm (this is just an example name) like:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Web;
public class SqlComm
{
// this is a shortcut for your connection string
static string DatabaseConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["dbConStr"].ConnectionString;
// this is for just executing sql command with no value to return
public static void SqlExecute(string sql)
{
using (SqlConnection conn = new SqlConnection(DatabaseConnectionString))
{
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.Connection.Open();
cmd.ExecuteNonQuery();
}
}
// with this you will be able to return a value
public static object SqlReturn(string sql)
{
using (SqlConnection conn = new SqlConnection(DatabaseConnectionString))
{
conn.Open();
SqlCommand cmd = new SqlCommand(sql, conn);
object result = (object)cmd.ExecuteScalar();
return result;
}
}
// with this you can retrieve an entire table or part of it
public static DataTable SqlDataTable(string sql)
{
using (SqlConnection conn = new SqlConnection(DatabaseConnectionString))
{
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.Connection.Open();
DataTable TempTable = new DataTable();
TempTable.Load(cmd.ExecuteReader());
return TempTable;
}
}
// sooner or later you will probably use stored procedures.
// you can use this in order to execute a stored procedure with 1 parameter
// it will work for returning a value or just executing with no returns
public static object SqlStoredProcedure1Param(string StoredProcedure, string PrmName1, object Param1)
{
using (SqlConnection conn = new SqlConnection(DatabaseConnectionString))
{
SqlCommand cmd = new SqlCommand(StoredProcedure, conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter(PrmName1, Param1.ToString()));
cmd.Connection.Open();
object obj = new object();
obj = cmd.ExecuteScalar();
return obj;
}
}
}
Okay, this only a class, and now you should know how to use it:
If you wish to execute a command like delete, insert, update etc. use this:
SqlComm.SqlExecute("TRUNCATE TABLE Table1");
but if you need to retrieve a specific value from the database use this:
int myRequiredScalar = 0;
object obj = new object();
obj = SqlComm.SqlReturn("SELECT TOP 1 Col1 FROM Table1");
if (obj != null) myRequiredScalar = (int)obj;
You can retrieve a bunch of rows from the database this way (others like other ways)
This is relevant to your sepecific question
int Col1Value = 0;
DataTable dt = new DataTable();
dt = SqlComm.SqlDataTable("SELECT * FROM myTable WHERE myPK='simpleText'");
if (dt.Rows.Count == 0)
{
// do something if the query return no rows
// you may insert the relevant redirection you asked for
}
else
{
// Get the value of Col1 in the 3rd row (0 is the first row)
Col1Value = (int)dt.Rows[2]["Col1"];
// or just make the other redirection from your question
}
If you need to execute a stored procedure with or without returning a value back this is the way to do that (in this example there are no returning value)
SqlComm.SqlStoredProcedure1Param("TheStoredProcedureName", "TheParameterName", TheParameterValue);
Again, for your specific question return the table using the SqlDataTable , and redirect if dt.Rows.Count >0
Have fun.
There are many ways: LINQ, SqlDataReader, SQLDataAdapter, according to what you want to read (single value, datatable ...), so here is an example:
using (SqlConnection con = new SqlConnection("SomeConnectionString"))
{
var cmd = new SqlCommand("select from myTable where myPK==N'"+ simpleText+ "'",con);
cmd.Connection.Open();
var sqlReader = cmd.ExecuteReader();
while(sqlReader.Read())
{
//Fill some data like : string result = sqlReader("SomeFieldName");
}
sqlReader.Close();
cmd.Connection.Close();
cmd.Dispose();
}

Categories