Run Stored Procedure and Check Value Exists or Not C# - c#

I have this stored procedure:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE ClientDelete
#clientid uniqueidentifier
AS
BEGIN
SET NOCOUNT ON;
UPDATE Clients SET enabled=1,editDate=GETUTCDATE() WHERE clientid=#clientid
END
Using this feature file:
Feature: ClientDelete
Scenario: Client Delete
Given a clean database
Given the following Clients table
| clientid | name | url | enabled | lastChangedBy | createDate | editDate |
| 1 | Client1 | https://test | true | test | 2000-01-01 | 2000-01-01 |
| 2 | Client2 | https://test | true | test | 2000-01-01 | 2000-01-01 |
When the "ClientDelete" stored procedure is run with the following parameters
| name | value |
| clientid | 11 |
Then the following is returned
| clientid | name | url | enabled | lastChangedBy | createDate | editDate |
| 1 | Client1 | https://test | false | test | 2000-01-01 | 2000-01-01 |
| 2 | Client2 | https://test | true | test | 2000-01-01 | 2000-01-01 |
C# Code:
[When(#"the ""(.*)"" stored procedure is run with the following parameters")]
public void WhenTheStoredProcedureIsRunWithTheFollowingParameters(string procName, Table table)
{
using (var con = CreateDBConnection())
{
using (var cmd = con.CreateCommand())
{
cmd.CommandText = procName;
cmd.CommandType = CommandType.StoredProcedure;
foreach (var row in table.Rows)
{
var param = cmd.CreateParameter();
param.ParameterName = row.Values.First();
if (param.ParameterName == "clientids")
{
param.SqlDbType = SqlDbType.Structured;
param.Value = new List<SqlDataRecord>()
{
ToSqlDataRecord(new Guid(row.Values.Last()))
};
}
else if (param.ParameterName == "docTypes")
{
param.SqlDbType = SqlDbType.Structured;
if (row.Values.Last() != "NULL")
{
param.Value = new List<SqlDataRecord>()
{
ToSqlDataRecord(row.Values.Last())
};
}
}
else if (row.Values.Last() != "NULL")
param.Value = row.Values.Last();
else
param.Value = DBNull.Value;
cmd.Parameters.Add(param);
}
var results = new DataTable();
using (var adapter = new SqlDataAdapter((SqlCommand)cmd))
{
adapter.Fill(results);
}
_context.Add("Results", results);
}
}
}
[Then(#"the following is returned")]
public void ThenTheFollowingIsReturned(Table table)
{
var results = _context.Get<DataTable>("Results");
Assert.AreEqual(table.Rows.Count, results.Rows.Count);
for (int i = 0; i < results.Rows.Count; i++)
{
var expectedRow = table.Rows[i];
var actualRow = results.Rows[i];
for (int j = 0; j < table.Header.Count; j++)
{
var name = table.Header.ElementAt(j);
var type = actualRow[name].GetType();
object expectedValue = expectedRow[name];
if (expectedValue.ToString().IsNullText())
expectedValue = null;
else if (type != typeof(DBNull))
expectedValue = TypeDescriptor.GetConverter(type).ConvertFromInvariantString(expectedRow[name]);
var actualValue = Convert.IsDBNull(actualRow[name]) ? null : actualRow[name];
Assert.AreEqual(expectedValue, actualValue, name);
}
}
}
#Then is not working as it's not returning anything from stored procedure so I want to check if the value updated or exists or not.
I have this too when and then used for multiple stored procedure which returns row data and is working fine, but does not work with add, delete, update.
Note: I need to do without adding output parameter to stored procedure.

After the update in your stored procedure add:
SELECT ##ROWCOUNT AS Result
This will return the number of rows affected by the previous update statement. You can then check in your C# code if the Result is > 0.
##ROWCOUNT documentation:
https://learn.microsoft.com/en-us/sql/t-sql/functions/rowcount-transact-sql?view=sql-server-ver15

You need to query the clients table again in your Then step. The DeleteClient stored procedure does not return anything, nor does it fill an output variable. Your only recourse is the query the clients table again in Then the following is returned. You can use the Table extension method CompareToSet(...) instead of doing the assertions manually yourself.

Related

DataGridView is not showing all columns from table

I have following table in my PostgreSQL database:
Table "public.ads"
Column | Type | Collation | Nullable | Default
----------------------+-----------------------------+-----------+----------+-----------------------------------
idad | integer | | not null | nextval('ads_idad_seq'::regclass)
uidowner | integer | | |
month | integer | | |
year | integer | | |
mileage | integer | | |
idmake | integer | | |
idmodel | integer | | |
idmotor | integer | | |
idbodytype | integer | | |
description | text | | |
createdat | timestamp without time zone | | not null |
optionalequipmentids | character varying[] | | |
photos | character varying[] | | |
price | integer | | |
generaldata | jsonb | | |
vehicledata | jsonb | | |
engineenvironment | jsonb | | |
conditionmaintenance | jsonb | | |
idfueltype | integer | | |
Indexes:
"ads_pk" PRIMARY KEY, btree (idad)
Foreign-key constraints:
"ads_idbodytype_fkey" FOREIGN KEY (idbodytype) REFERENCES bodytype(idbodytype) ON UPDATE CASCADE
"ads_idfueltype_fkey" FOREIGN KEY (idfueltype) REFERENCES fueltype(idfueltype) ON UPDATE CASCADE
"ads_idmake_fkey" FOREIGN KEY (idmake) REFERENCES make(idmake) ON UPDATE CASCADE
"ads_idmodel_fkey" FOREIGN KEY (idmodel) REFERENCES model(idmodel) ON UPDATE CASCADE
"ads_idmotor_fkey" FOREIGN KEY (idmotor) REFERENCES motor(idmotor) ON UPDATE CASCADE
I created method for filling DataGridView with data from table above, and here is the code part:
private void FillDataGridAds()
{
if (!connected) return;
string cmdString = string.Empty;
try
{
cmdString = "SELECT * FROM ads";
NpgsqlCommand command = new NpgsqlCommand(cmdString, conn);
NpgsqlDataAdapter da = new NpgsqlDataAdapter(command);
DataTable dt = new DataTable();
da.Fill(dt);
dataGridAds.DataSource = dt.DefaultView;
}
catch (NpgsqlException ex)
{
textBox1.AppendText("PostgreSQL exception: " + ex.Message + Environment.NewLine);
}
catch (Exception ex)
{
textBox1.AppendText("Exception ex: " + ex.Message + Environment.NewLine);
}
}
Designer part of code of my dataGridAds
//
// dataGridAds
//
this.dataGridAds.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.dataGridAds.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridAds.ContextMenuStrip = this.contextMenuStrip1;
this.dataGridAds.Location = new System.Drawing.Point(9, 49);
this.dataGridAds.Name = "dataGridAds";
this.dataGridAds.RowHeadersWidth = 51;
this.dataGridAds.RowTemplate.Height = 29;
this.dataGridAds.Size = new System.Drawing.Size(1326, 549);
this.dataGridAds.TabIndex = 0;
this.dataGridAds.CellEndEdit += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridAds_CellEndEdit);
//
Problem:
For some reason when method for filling dataGridAds is triggered, dataGridAds is displaying all columns except optionalequipmentids and photos, so does anybody know where can be a problem, I was trying to figured out where problem might be, but unsuccessfully, have same issue with another tables in my appplication and want to fix as soon as possible, thank you all in advance.
The columns are both data-type character varying[] I assume that the columns in other tables with the same problem are the same data-type.
You could try using CAST. Does the following script with a nomnative SELECT with CASE for the problem columns work?
If CAST( ... AS VARCHAR(1000)) doesn't work you could also try
CAST( ... AS VARCHAR)
private void FillDataGridAds()
{
if (!connected) return;
string cmdString = string.Empty;
try
{
cmdString =
"SELECT
idad ,
uidowner ,
month ,
year ,
mileage ,
idmake ,
idmodel ,
idmotor ,
idbodytype ,
description ,
createdat ,
CAST( optionalequipmentids AS VARCHAR(1000)),
CAST( photos AS VARCHAR(1000)),
price ,
generaldata ,
vehicledata ,
engineenvironment ,
conditionmaintenance ,
idfueltype FROM ads";
NpgsqlCommand command = new NpgsqlCommand(cmdString, conn);
NpgsqlDataAdapter da = new NpgsqlDataAdapter(command);
DataTable dt = new DataTable();
da.Fill(dt);
dataGridAds.DataSource = dt.DefaultView;
}
catch (NpgsqlException ex)
{
textBox1.AppendText("PostgreSQL exception: " + ex.Message + Environment.NewLine);
}
catch (Exception ex)
{
textBox1.AppendText("Exception ex: " + ex.Message + Environment.NewLine);
}
}

c# LINQ find value in datareader

This is my table on MySQL database :
+----------+--------+---------+
| UserName | Region | UsercIX |
+----------+--------+---------+
| a123456 | X410 | NULL |
| a123456 | X420 | 1 |
| a123456 | X430 | NULL |
| a123456 | X440 | 1 |
+----------+--------+---------+
The user a123456 is write enabled for X420 and X440 Region (UsercIX=1) and reading for X410 and X430 Region (UsercIX=NULL).
I need to find in this table -via LINQ or your suggestion- only values equals to 1 in the column UsercIX, because with DataReader extracting the first value of the column which is null.
Please an you help me ?
My code below
using (OdbcDataReader reader = command.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
int UsercIX = Convert.ToInt32(reader["UsercIX"]); //IS NULL
}
}
}
Edit #01
using (OdbcDataReader reader = command.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
int UsercIX = reader.GetInt32(6);
}
}
}
May i suggest doing a try parse on the value?
int number;
bool success = Int32.TryParse((reader["UsercIX"], out number);
if (success)
{
// it worked, yay
}
else
{
// 😥
}
I think you should access the values in this way:
**SqlDataReader** reader = command.ExecuteReader();
int UsercIX = reader.GetInt32(2);
with in the while loop.
The colums start with 0
Eventually you run in an error when accesing Null-value then use a try() {} catch() {} structure to avoid this.
- Hope this helps!
Here is a complete example for mysql;
public void CreateMySqlDataReader(string mySelectQuery, MySqlConnection myConnection)
{
MySqlCommand myCommand = new MySqlCommand(mySelectQuery, myConnection);
myConnection.Open();
MMySqlDataReader myReader;
myReader = myCommand.ExecuteReader();
try
{
while(myReader.Read())
{
Console.WriteLine(myReader.GetString(0));
}
}
finally
{
myReader.Close();
myConnection.Close();
}
}

some selected fields as Pivote column ASP.NET

I want to show some selected columns as my SQL column and the rest of the column should be pivot. My output should be: Please help me any idea ?
Pivot table
ID | Employee_ID | 01-sep-2019 | 02-sep-2019 | 03-sep-2019
───┼─────────────┼─────────────┼─────────────┼────────────
1 | 1001 | P | A | P
2 | 1002 | A | P | A
3 | 1003 | A | P | P
Original table
ID | Employee_ID |STATUS | Created_Date
───┼─────────────┼───────┼─────────────
1 | 1001 | P | 01-sep-2019
2 | 1002 | A | 02-sep-2019
3 | 1003 | P | 03-sep-2019
I use 2 `GridView to show data but it's applicable for all column that I don't need. Could you please help me?
private DataTable PivotTable(DataTable origTable) {
DataTable newTable = new DataTable();
DataRow dr = null;
//Add Columns to new Table
for (int i = 0; i <= origTable.Rows.Count; i++) {
newTable.Columns.Add(new DataColumn(origTable.Columns[i].ColumnName, typeof(String)));
}
//Execute the Pivot Method
for (int cols = 0; cols < origTable.Columns.Count; cols++) {
dr = newTable.NewRow();
for (int rows = 0; rows < origTable.Rows.Count; rows++) {
if (rows < origTable.Columns.Count) {
dr[0] = origTable.Columns[cols].ColumnName; // Add the Column Name in the first Column
dr[rows + 1] = origTable.Rows[rows][cols];
}
}
newTable.Rows.Add(dr); //add the DataRow to the new Table rows collection
}
return newTable;
}
private void BindGridView() {
string strConnString = ConfigurationManager.ConnectionStrings["SQLDBConnection"].ConnectionString;
SqlConnection con = new SqlConnection(strConnString);
try {
con.Open();
string sqlStatement = "SELECT Top(5)* FROM tbl_QC_Attandence";
SqlCommand sqlCmd = new SqlCommand(sqlStatement, con);
SqlDataAdapter sqlDa = new SqlDataAdapter(sqlCmd);
DataTable dt = new DataTable();
sqlDa.Fill(dt);
if (dt.Rows.Count > 0) {
//Bind the First GridView with the original data from the DataTable
grdorignal.DataSource = dt;
grdorignal.DataBind();
//Pivot the Original data from the DataTable by calling the
//method PivotTable and pass the dt as the parameter
DataTable pivotedTable = PivotTable(dt);
grdpivote.DataSource = pivotedTable;
grdpivote.DataBind();
}
} catch (System.Data.SqlClient.SqlException ex) {
string msg = "Fetch Error:";
msg += ex.Message;
throw new Exception(msg);
} finally {
con.Close();
}
}
ORIGINAL TABLE
ID Employee_ID STATUS Created_Date
1 1001 P 01-sep-2019
2 1002 A 02-sep-2019
3 1003 P 03-sep-2019
PIVOT TABLE
ID Employee_ID 01-sep-2019 02-sep-2019 03-sep-2019
1 1001 P A P
2 1002 A P A
3 1003 A P P
I have create a dynamic query which can help you, but null can be replaced with 'A' in code side, try below one
DECLARE
#columns NVARCHAR(MAX) = '',
#sql NVARCHAR(MAX) = '',
#SelectColumnNames AS NVARCHAR(MAX);
SELECT
#columns += QUOTENAME([Created_Date]) + ','
FROM
Employee
ORDER BY
[Created_Date];
SET #columns = LEFT(#columns, LEN(#columns) - 1);
Select #SelectColumnNames = ISNULL(#SelectColumnNames + ',','')
+ 'ISNULL(' + QUOTENAME([STATUS]) + ', 0) AS '
+ QUOTENAME([STATUS])
from (SELECT distinct [STATUS] from Employee) as Employees
print #SelectColumnNames
SET #sql =
N'Select * from(
select Created_Date,[STATUS],ID,Employee_ID
from Employee
)t
PIVOT(
MAX([STATUS])
FOR [Created_Date] IN ('+ #columns +')
) AS pivot_table
';
EXECUTE sp_executesql #sql;

Duplicating data in crystal report with MySQL and C#

I have a problem in displaying the data in crystal report using left join. When i use "where no_barang = 2" in Phpmyadmin is working. But in crystalreport not working (the data is duplicate, and showing all data).
table "barang"
no_barang | nama_barang | harga_barang
1 | sepatu | 25000
2 | baju | 47000
table "pelanggan"
no_pelanggan | nama_pelanggan
1 | Sugeng Agung Suganda
2 | Babay Azifahmi
table "pembelian"
no_order | no_pelanggan | no_barang | jumlah
1 | 1 | 2 | 2
2 | 2 | 1 | 1
This my code in crystalreport
MySqlParameter p;
MySqlConnection conn = new MySqlConnection("database=cs_reportmultitables;server=localhost;uid=root;pwd=");
public View(string sTitle)
{
InitializeComponent();
try
{
DataSet ds = new DataSet();
string query;
p = new MySqlParameter("#no_order", MySqlDbType.String);
p.Value = sTitle;
query = "SELECT pembelian.no_order, pelanggan.nama_pelanggan, barang.nama_barang, barang.harga_barang, pembelian.jumlah FROM pembelian LEFT JOIN pelanggan ON pembelian.no_pelanggan = pelanggan.no_pelanggan LEFT JOIN barang ON pembelian.no_barang = barang.no_barang WHERE no_order=#no_order";
MySqlDataAdapter dscmd = new MySqlDataAdapter(query, conn);
dscmd.SelectCommand.Parameters.Add(p);
dscmd.Fill(ds);
RPT cryds = new RPT();
cryds.SetDataSource(ds.Tables[0]);
crystalReportViewer1.ReportSource = cryds;
crystalReportViewer1.Refresh();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
conn.Close();
}
conn.Close();
}
Trying to display number 2 and my output was this:
no_order | nama_pelanggan | nama_barang | harga_barang | jumlah
1 | Sugeng Agung Suganda | sepatu | 25000 | 2
2 | Babay Azifahmi | sepatu | 25000 | 1
It duplicate in "nama_barang" and "harga_barang", should display data like this:
2 | Babay Azifahmi | sepatu | 25000 | 1
Please help me if anyone know?

Reference data in SQLDataReader by column and rows or any alternative

I am running a stored procedure and the result is this format
+------+--------+-----+-------+
| ID | Resign | Sum | Count |
+------+--------+-----+-------+
| 1234 | 0 | 400 | 3 |
| 1234 | 1 | 800 | 4 |
+------+--------+-----+-------+
I tried this code to reference the values returned by the query but, it seem not working the way I want it
if (conn.State != ConnectionState.Open)
conn.Open();
SqlCommand sc = new SqlCommand();
sc.CommandText = "usp_GetResignPool";
sc.CommandType = CommandType.StoredProcedure;
sc.Connection = conn;
sc.Parameters.Add(AddParam(EndDate, "#EndDate"));
sc.Parameters.Add(AddParam(am_id, "#id"));
SqlDataReader reader;
reader = sc.ExecuteReader();
while (reader.Read())
{
if reader. // lost here
}
How can I do something like this. ↓
int resigned = 0, resign_count = 0, not_resigned = 0, notresign_count =0;
if (read["Resigned"] == 1)
{
resigned = read["sum"];
resign_count = read["count"];
}
else
{
not_resigned = read["sum"];
notresign_count = read["count"];
}
It is not important that I used SQLDataReader.
Edit: Real column names
ID Resigned sum count
--------- ----------- ---------------------- -----------
It didn't work because you don't have a column in your table named "Resigned", like you have when you are working with your SqlDataReader.
EDIT: I think the root of the problem is the way you are adding parameters. AddParam() is not the method you want to be using. Therefore, your result set is probably empty.
....
SqlCommand sc = new SqlCommand();
sc.CommandText = "usp_GetResignPool";
sc.CommandType = CommandType.StoredProcedure;
sc.Connection = conn;
sc.Parameters.AddWithValue("#EndDate", EndDate);
sc.Parameters.AddWithValue("id", am_id);
SqlDataReader reader;
reader = sc.ExecuteReader();
using (reader = sc.ExecuteReader())
{
while (reader.Read())
{
if (Convert.ToInt32(read["Resign"]) == 1)
{
resigned = Convert.ToInt32(read["Sum"]);
resign_count = Convert.ToInt32(read["Count"]);
}
else
{
not_resigned = Convert.ToInt32(read["Sum"]);
notresign_count = Convert.ToInt32(read["Count"]);
}
}
}
Notice how I changed your element indicator to "Resign". This needs to match the column that is returned in your dataset. Or, you could use a column number to get this, like so:
if (Convert.ToInt32(read[1]) == 1)
{
resigned = Convert.ToInt32(read[2]);
resign_count = read[3];
}
else
{
not_resigned = Convert.ToInt32(read[2]);
notresign_count = Convert.ToInt32(read[3]);
}
Also, keep in my that in every iteration or your while loop, you'll be overwriting the variables resigned, resign_count or not_resigned and notresign_count.
Would this work?
int resign = 0;
int not_resign = 0;
int resign_count = 0;
int not_resign_count = 0;
while (reader.Read())
{
if (Convert.ToInt32(reader["Resigned"]) == 1)
{
resign = Convert.ToInt32(reader["Sum"]);
resign_count = Convert.ToInt32(reader["Count"]);
}
else
{
not_resign = Convert.ToInt32(reader["Sum"]);
not_resign_count = Convert.ToInt32(reader["Count"]);
}
}
Can you post your query from the procedure?
Are the column names really "Sum" and "Count"?
There are reserved words, maybe you should try using "AS" and give other names to these to columns in the projection.

Categories