I have a stored procedure created in my SQL Server 2012 database that selects data from multiple tables. In C#, I use this procedure to show data in a datagridview.
Issue: when I execute the query in SQL Server, I get the correct result which returns 3 rows, but in C#, it returns only 2 rows.
Query:
SELECT DISTINCT
Employee.Employee_No AS 'Badge'
,Employee.Employee_Name_Ar AS 'Emp Name'
,Employee.Basic_Salary AS 'Basic'
,Employee.Current_Salary AS 'Current'
,Attendance.Present
,Attendance.Leave
,Attendance.Othe_Leave AS 'OL'
,Pay_Slip.Salary_Amount AS 'Sal. Amt.'
,(ISNULL(Pay_Slip.OverTime1_Amount, 0.00) + ISNULL(Pay_Slip.OverTime2_Amount, 0.00)) AS 'O/T Amt.'
,(ISNULL(Pay_Slip.Salary_Amount, 0.00) + ISNULL(ISNULL(Pay_Slip.OverTime1_Amount, 0.00) + ISNULL(Pay_Slip.OverTime2_Amount, 0.00), 0.00)) AS 'Sal. & O/T'
,Pay_Slip.Trasnport AS 'Allow'
,Pay_Slip.CostofLiving AS 'O.Allow'
,Pay_Slip.Gross_Salary AS 'T Salary'
,Pay_Slip.Insurance1_Amount AS 'ss 7%'
,Pay_Slip.Insurance2_Amount AS 'ss 11%'
,(ISNULL(Pay_Slip.Insurance1_Amount, 0.00) + ISNULL(Pay_Slip.Insurance2_Amount, 0.00)) AS 'Total s.s'
,Pay_Slip.Tax
,Pay_Slip.Personal_Loans AS 'Advance'
,Pay_Slip.Other_Deductions AS 'Ded.'
,Pay_Slip.Net_Salary AS 'Net'
FROM Pay_Slip
LEFT JOIN Employee ON Pay_Slip.Employee_No = Employee.Employee_No
LEFT JOIN Attendance ON Pay_Slip.Employee_No = Attendance.Employee_No
WHERE Pay_Slip.Month = '5'
AND Pay_Slip.Year = '2020'
AND Attendance.Month = '5'
AND Attendance.Year = '2020'
Executing this query in SQL Server returns 3 rows which are the employee slips on May-2020 (They all have values in May-2020).
C# code:
private void dateTimePicker_ReportDate_ValueChanged(object sender, EventArgs e)
{
try
{
DateTime date = dateTimePicker_ReportDate.Value;
String Month = dateTimePicker_ReportDate.Value.ToString("MM");
String Year = dateTimePicker_ReportDate.Value.ToString("yyyy");
String str = "server=localhost;database=EasyManagementSystem;User Id=Jaz;Password=Jaz#2020;Integrated Security=True;";
String query = "Execute EMP_PAY_ATT_Selection #Month, #Year";
SqlConnection con = null;
con = new SqlConnection(str);
SqlCommand cmd= new SqlCommand(query, con);
cmd.Parameters.Add("#Month", SqlDbType.Int).Value = Convert.ToInt32(Month);
cmd.Parameters.Add("#Year", SqlDbType.Int).Value = Convert.ToInt32(Year);
SqlDataReader sdr;
con.Open();
sdr = cmd.ExecuteReader();
if (sdr.Read())
{
DataTable dt = new DataTable();
dt.Load(sdr);
dataGridView_Report.DataSource = dt;
dataGridView_Report.EnableHeadersVisualStyles = false;
dataGridView_Report.ColumnHeadersDefaultCellStyle.BackColor = Color.LightBlue;
}
else
{
dataGridView_Report.DataSource = null;
dataGridView_Report.Rows.Clear();
}
con.Close();
}
catch (Exception es)
{
MessageBox.Show(es.Message);
}
}
Again, when running this, it only returns 2 rows on the datagridview. While it should be 3 rows.
These are the tables:
The DbDataReader.Read method advances the reader to the next record.
There is no way to rewind a data reader. Any methods that you pass it to will have to use it from whatever record it is currently on.
If you want to pass the reader to DataTable.Load(), do not Read from it yourself. If you merely want to know if it contains records, use HasRows.
Related
I am trying to increase the value from a database after each row is added to a label, I get it to increase until the 3rd Invoice. Here is my code:
public void loadInv()
{
>declare variables
int i;
int y;
y = 0;
i = 1;
>declare data source
string datasource = #"Data Source=DESKTOP-VVM3FB0\WARRENDB;Initial Catalog=mAdjustments; User ID=WarrenDB; password=//purposely taken out; ";
>declare selectquery variable
string selectQuery;
>create sql connection
SqlConnection con = new SqlConnection(datasource);
>open sql connection
con.Open();
>initialize the select query with sql query
selectQuery = #"SELECT MAX(InvoiceNum) FROM Invoices";
>initialize command with parameter of select query with connection
SqlCommand com = new SqlCommand(selectQuery, con);
> declare data reader and execute the command
SqlDataReader dr = com.ExecuteReader();
>conditional statement while reader is reading from database
while (dr.Read())
{
>if database has no row
if (dr.IsDBNull(y))
{
lblInvNum.Text = 1.ToString();
}
>if database has row
else if (dr.HasRows)
{
>>count the amount on the field and add 1
i = dr.FieldCount + 1;
i = i + 1;
>>assign to label
lblInvNum.Text = i.ToString();
}
}
}
Can someone please help me figure this out?
It seems u are looking for last inserted row so you can use output parameter in sql query and scope_variable to return last inserted row ID to your out parameter
I have two DateTimePicker control on my win form...and all i want is when the user select the datetimepicker(from: ) and ( To: ) the datagridview shows the selected date and year that the user selected..........here's my code.... i need the sort thing
P.S: i used STORED PROCEDURE
public void period()
{
cnn.Open();
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "sp_insertcategory";
cmd.Connection = cnn;
SqlDataReader rdr = cmd.ExecuteReader();
if (rdr.HasRows)
{
while (rdr.Read())
{
int n = metroGrid1.Rows.Add();
metroGrid1.Rows[n].Cells[0].Value = rdr[0].ToString();
metroGrid1.Rows[n].Cells[1].Value = rdr[1].ToString();
metroGrid1.Rows[n].Cells[2].Value = rdr[2].ToString();
metroGrid1.Rows[n].Cells[3].Value = rdr[3].ToString();
metroGrid1.Rows[n].Cells[4].Value = rdr[4].ToString();
metroGrid1.Rows[n].Cells[5].Value = rdr[5].ToString();
metroGrid1.Rows[n].Cells[6].Value = rdr[6].ToString();
}
}
cnn.Close();
}
You can achieve the same from SQL query (In your case stored procedure itself). Just add below syntax in your SQL query to sort the data in descending order..
ORDER BY post_datetime DESC //post_datetime is columnName which contains DateTime
ASC can be used if you need sorting in ascending order.
Details about order by can be found at https://www.w3schools.com/sql/sql_orderby.asp
I have a form which use two tables to insert the data.
Some column in the form would be like:
scholarship name, course, year
Two tables that are involved are:
scholarshipDetail , scholarshipCourse.
scholarshipDetail table has scholarshipName and year
scholarshipCourse table has scholarshipID, course
scholarshipDetail:
schid schName year
-----------------------------
1 star 2015
2 moon 2016
scholarshipCourse:
schID course
------------------
1 maths
1 english
2 maths
Assuming that the new user wants to add new scholarship which means the id will 3 and it insert into two tables. How do I that? (MANAGED TO INSERT ALR)
NEW ERROR:
EDITED
public DataTable test(string name, string course)
{
string insertsql = "INSERT INTO Table1(schName) OUTPUT INSERTED.addID values (#schName)";
SqlCommand cmd = new SqlCommand(insertsql,conn);
cmd.Parameters.AddWithValue("#schName", name);
conn.Open();
int i = cmd.ExecuteNonQuery();
var table1Id = (int)cmd.ExecuteScalar();
string insertsql1 = "INSERT INTO Table2(ScholarshipID, DiplomaCourse) VALUES (#id, #course)";
SqlCommand cmd2 = new SqlCommand(insertsql1, conn);
cmd2.Parameters.AddWithValue("#id", table1Id);
cmd2.Parameters.AddWithValue("#course", course);
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = cmd;
da.SelectCommand = cmd2;
DataTable dt = new DataTable();
da.Fill(dt);
return dt;
}
The output in my table is
Table1
schID schname
-------------------
1 jj
2 jj
Table2
TableID schID Course
------------------------------
1 2 Maths
the data is being inserted twice in Table1. why is that so? (SOLVED)
Edited:
Now the problem is, there will be checkboxes which allow the user to choose which course is applicable for the scholarship.
When the user click all checkbox, only the last checkbox will insert into database.
In my codebehind(cs):
protected void Button1_Click(object sender, EventArgs e)
{
// addScholarship[] test = new addScholarship[1];
string course = "";
string Name = schName.Text;
if (DIT.Checked )
{
course = "DIT";
}
if (DFI.Checked)
{
course = "DFI";
}
addScholarship[] insertName = new addScholarship[1];
addScholarship insertedName = new addScholarship(Name,course);
scholarshipBLL obj = new scholarshipBLL();
DataTable dt = obj.test(Name, course);
}
For the latest problem you posted.
You are calling obj.test method only once after all the if blocks.
So the "course" variable will have value from the latest if block where the condition is true.
You need to call DataTable dt = obj.test(Name, course); method in every if block. That means if checkbox is checked you call insert row. If not checked then you don't insert the row.
Following is the code you should put in your button_click.
string course = "";
string Name = schName.Text;
scholarshipBLL obj = new scholarshipBLL();
List<addScholarship> addScholarshipList= new List<addScholarship>();
addScholarship scholarship;
if (DIT.Checked )
{
scholarship = new addScholarship(Name,course);
addScholarshipList.Add(insertedName);
course = "DIT";
DataTable dt = obj.test(Name, course);
}
if (DFI.Checked)
{
scholarship = new addScholarship(Name,course);
addScholarshipList.Add(insertedName);
course = "DFI";
DataTable dt = obj.test(Name, course);
}
You are executing the command twice.
int i = cmd.ExecuteNonQuery();
var table1Id = (int)cmd.ExecuteScalar();
You need to execute only one. I think removing cmd.ExecuteNoteQuery would solve your issue.
BEGIN;
INSERT INTO scholarshipDetail(schid,schName,year) VALUES(3,'sun',2017);
INSERT INTO scholarshipCourse(schID,course) VALUES(LAST_INSERT_ID(),'science');
COMMIT;
I have 2 tables in an Access database. Currently I have a c# winform app in VS 2015 with 2 forms that have a search button on each that will search that particular table The only similarity is the SerialNumber field but it is unrelated as the Serial Numbers for each table are for different equipment. Any tips on how to perform a search of both tables with 1 button?
private void searchItembtn_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(serialSearch.Text))
{
try
{
connection.Open();
OleDbCommand command = new OleDbCommand();
command.Connection = connection;
command.Transaction = transaction;
command.Parameters.Add("#searchSerial", OleDbType.VarWChar).Value = serialSearch.Text;
string searchFB = "SELECT * FROM Inventory WHERE SerialNumber = #searchSerial";
command.CommandText = searchFB;
connection.Close();
OleDbDataAdapter db = new OleDbDataAdapter(command);
DataTable dt = new DataTable();
db.Fill(dt);
dataGridFB.DataSource = dt;
}
catch (OleDbException ex)
{
MessageBox.Show(ex.Message);
connection.Close();
}
searchHide();
connection.Close();
}
}
Create a UNION query in Access, that will contain data from both tables:
SELECT
SerialNumber,
InventoryField1 AS Field1,
InventoryFieldN AS FieldN
FROM Inventory
UNION ALL
SELECT
SerialNumber,
CompetitiveField1 AS Field1,
CompetitiveFieldN AS FieldN
FROM Competitive
Then use this query as the row source in your command (CompetitiveInventory would be the query name):
string searchFB = "SELECT * FROM CompetitiveInventory WHERE SerialNumber=#searchSerial";
Alternatively, a JOIN may be what you want, depending on the requirement.
I am going to have multiple processes running at the same time so what I tried to do here is fetch 1000 rows and then update the rows i selected.. below are my Select and Update functions notice i call the update function right after closing the connection in the select function
public List<string> Select()
{
string set;
string query = "SELECT * FROM master WHERE attempted='0' LIMIT 1000";
List<string> list = new List<string>();
if (this.OpenConnection() == true)
{
MySqlCommand cmd = new MySqlCommand(query, connection);
MySqlDataReader dataReader = cmd.ExecuteReader();
while (list.Count() < 1000)
{
dataReader.Read();
string email = dataReader["email"].ToString();
var m = dataReader["attempted"];
if (m.ToString() == "0")
{
list.Add(email);
}
}
dataReader.Close();
this.CloseConnection();
Update();
return list;
}
else
{
return list;
}
}
public void Update()
{
if (this.OpenConnection() == true)
{
string query = "UPDATE master SET attempted='1' WHERE ( SELECT * FROM master WHERE attempted='0' LIMIT 1000 )";
MySqlCommand cmd = new MySqlCommand(query, connection);
cmd.CommandText = query;
cmd.ExecuteNonQuery();
this.CloseConnection();
}
}
the exception i am getting it operand must contain 1 column(s)..
What am I doing wrong?
Why can't you just create a separate column, or even a table? Then write a basic Query at the SQL level or a Procedure to modify the value? Then the other applications can just test the value of the column or table.
Example:
UPDATE [dbo].[Customer]
SET [GotEmail] = 1
WHERE (
SELECT [Email]
FROM [dbo].[Customer]
);
Or something basic like that? Another example would be:
UPDATE accounts
SET (contact_last_name, contact_first_name) =
(SELECT last_name, first_name FROM salesmen
WHERE salesmen.id = accounts.sales_id);
Does a simple query like so not solve your issue?
If my response is not clear... I'll try and clarify my thought process.