I have a stored procedure with the following code, it works fine in sql server. I need to use the returned rows to work with the stacked column chart. I don't know how to receive these rows, though I have tried to do so with code given after the stored procedure code. I would really appreciate if anyone could find out where I am doing something wrong. Thank you :)
Stored Procedure Code:
ALTER PROCEDURE [dbo].[weekly]
#id_beleg int /* CONTAINS THE ID OF THE MACHINE FOR WHICH THE NUMBER OF ORDERS IS REQUIRED*/
AS
BEGIN
DECLARE #montag DATETIME
DECLARE #weekend DATETIME
SET #montag = DATEADD(wk, DATEDIFF(wk,0,GETDATE()), 0)
/* SET #MONTAG VARIABLE TO THE DATE ON MONDAY OF THE CURRENT WEEK*/
SET #weekend = dateadd(day, 6, #montag)
/* SET #WEEKEND VARIABLE TO THE DATE ON SUNDAY OF THE CURRENT WEEK*/
/* CONTAINS ALL RECORDS OF one PROCESS FOR THE CURRENT WEEK*/
CREATE TABLE #WeeklySieben
(
Tag datetime,
Aufträge_anzahl int,
Anlage varchar(30)
);
INSERT INTO #WeeklySieben (Tag, Aufträge_anzahl, Anlage)
SELECT *
FROM
dbo.Sieben
WHERE
Tag BETWEEN #montag AND GETDATE()
ORDER BY Tag
DECLARE #tempdate datetime
/* CONTAINS ONLY THE UNIQUE MACHINE NAMES*/
CREATE TABLE #Anlage_Sieben
(
Anl varchar(30)
)
/* CONTAINS DATE FOR ALL DAYS OF THE CURRENT WEEK*/
CREATE TABLE #alldays
(
days datetime
)
INSERT INTO #Anlage_Sieben (Anl)
SELECT KURZTEXT as Anl
FROM dbo.tblBELEGUNGSEINHEIT
WHERE ID in (SELECT ID_BELEGUNGSEINHEIT FROM dbo.tblPROZESS_BELEGUNGSEINHEIT WHERE ID_PROZESS = 5)
/* SELECT MACHINE ID WHERE PROCESS IS number 5*/
WHILE #montag <= #weekend
BEGIN
INSERT INTO #alldays (days)
SELECT days = #montag
SET #tempdate= #montag
SET #montag = dateadd(day, 1,#tempdate)
END
/* MACHINE NAME * WEEKDAYS DATE*/
CREATE TABLE #weekdays
(
daydate datetime,
Anlage varchar(30)
)
INSERT INTO #weekdays (daydate, Anlage)
SELECT d.days as daydate
, a.Anl as Anlage
FROM #Anlage_Sieben a
CROSS JOIN #alldays d
/* SELECT NUMBER OF ORDERS ON A PARTICULAR MACHINE FOR ALL WEEK DAYS*/
Select case
when Aufträge_anzahl is null then '0'
else Aufträge_anzahl
end
from #WeeklySieben W right join #weekdays wd on W.Anlage = wd.Anlage and W.Tag = wd.daydate
where wd.Anlage in (select KURZTEXT from dbo.tblBELEGUNGSEINHEIT where ID = #id_beleg )
END
C# Code:
try
{
int a;
string sql = "weekly";
SqlDataAdapter dp = new SqlDataAdapter();
SqlCommand c = null;
SqlDataReader r = null;
DataSet ds = new DataSet();
DataTable dt = new DataTable();
//For creating 'raum' number of stacked column bars
for (int i = 0; i < raum; i++)
{
c = new SqlCommand(sql, conn);
c.CommandType = CommandType.StoredProcedure;
c.Parameters.Add("#raumn", SqlDbType.Int).Value= (int)dblOrders[i];
r = c.ExecuteReader();
dp.SelectCommand = c;
dp.Fill(ds, "Aufträge_anzahl");
dt = ds.Tables["Aufträge_anzahl"];
//For adding points to a stacked column bar
for (int j = 0; j < dt.Rows.Count; j++)
{
a = Convert.ToInt32(dt.Rows[j]);
Chart1.Series[seriesArray[j]].Points.AddY(a);
}
Chart1.DataBind();
dtSr.Clear();
}
}
catch (SqlException ex)
{
Console.WriteLine("SQL Error" + ex.Message.ToString());
}
dblorders is the double array which holds the IDs for different machines, raum is the number of total machines. The code generates no error, but it does not retrieve back the data in the chart.
Related
using(DAD_BaldipContext ctx = new DAD_BaldipContext())
{
int month = 02;
int year = 2018;
var x = ctx.TruckRentalPb.FromSqlRaw("TotalMonthlyRental #month, #year", month, year).ToList();
textbox.Text = x[1].TruckId.ToString();
}
Stored procedure:
ALTER PROCEDURE [dbo].[TotalMonthlyRental]
#month int,
#year int
AS
BEGIN
SET NOCOUNT ON;
SELECT MONTH(RentDate) AS Month, SUM(TotalPrice) AS TotalRental
FROM [TruckRental-PB]
WHERE MONTH(RentDate) = #month
AND YEAR(RentDate) = #year
GROUP BY MONTH([RentDate]), YEAR(RentDate)
END
I am trying to call this stored procedure called TotalMonthlyRental which requires two parameters month and year.
I have hard coded a month and year however I am getting the error must declare the scalar variable month.
In FromSqlRaw you can either construct DbParameter objects,
int month = 02;
int year = 2018;
var pMonth = new SqlParameter("#month", System.Data.SqlDbType.Int);
var pYear = new SqlParameter("#year", System.Data.SqlDbType.Int);
pMonth.Value = month;
pYear.Value = year;
var x = ctx.TruckRentalPb.FromSqlRaw("exec TotalMonthlyRental #month, #year;", pMonth, pYear).ToList();
or use a format-style string.
int month = 02;
int year = 2018;
var x = ctx.TruckRentalPb.FromSqlRaw("exec TotalMonthlyRental {0}, {1};", month, year).ToList();
Notice that there's no ambiguity as you are passing a format string and additional arguments, so EF knows to parameterize the query.
Also you can use FromSqlInterpolated which handles the parameterization for you if your query is an interpolated string:
int month = 02;
int year = 2018;
var x = ctx.TruckRentalPb.FromSqlInterpolated($"exec TotalMonthlyRental {month}, {year};").ToList();
If you passed that interpolated string to FromSqlRaw the string interpolation would happen before the query is passed in and it wouldn't be parameterized.
You don't need exec in your statement. Use this:
int month = 02;
int year = 2018;
var x = ctx.TruckRentalPb.FromSqlInterpolated($"TotalMonthlyRental {month}, {year}").AsNoTracking().ToList();
Also, AsNoTracking() may be beneficial for reads from the database and saves another 30% or so in execution time.
Check this blog entry from c-sharpcorner
Another note: make sure your variables are in the exact same order as they are in your stored procedure.
I'm using c# winform sql server
In my database I try to manage the employee vacations in my small company so I was created two tables
first table called tblMember
idMember (PK, int, not null)
memberName (varchar(50), null)
that table related in one to many relationship to
second table called tblVacations
idVacation (PK, int, not null)
vacationStart (date, null)
vacationEnd (date, null)
idMember_L(FK, int, null)
then I created a form with two datagridview the first called dg_member populate its data (names from tblMember) throw a stored procedure
the second datagridview dgVacation populate the related data
now I want to colored with red the name in dg_member who absent today ( today is fall between vacationStart and vacationEnd ) and if the member is coming today ( today equal vacationEnd ) the name turn to green
i tried the code :
private void dgMember_Grade_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
foreach (DataGridViewRow Myrow in dgMember_Grade.Rows)
{
var cvStart = dgVacation.Rows[0].Cells[1].Value;
var cvEnd = dgVacation.Rows[0].Cells[2].Value;
if (cvStart == null || cvStart == DBNull.Value)
continue;
DateTime startDate = Convert.ToDateTime(cvStart);
DateTime endDate = Convert.ToDateTime(cvEnd);
if (startDate < DateTime.Now && endDate > DateTime.Now)
{
Myrow.DefaultCellStyle.BackColor = Color.Red;
}
else if (endDate == DateTime.Now)
{
Myrow.DefaultCellStyle.BackColor = Color.Green;
}
}
}
but it gives me an error
Index was out of range. Must be non-negative and less than the size of the collection.
thank you
declare #tmw Date = DATEADD(day, 1,getdate())
select
m.MemberName
, case when t.idMember_L is null then 'False' else 'True' end as OnHoliday
, case when (select count (tm.idMember_L) from tblVacations tm where
m.idMember = tm.idMember_L and
t.vacationStart <= #tmw and t.vacationEnd >= #tmw ) > 0
then 'False' else 'True' end as OnHolidayTomorrow
from tblMember m
left outer join tblVacations t
on m.idMember = t.idMember_L and
t.vacationStart <= getdate() and t.vacationEnd >= getdate()
So first here is my C# code and then comes the stored procedure.
public DataTable GetCourseHighPass(String tmpCourse)
{
command.Connection = OpenConnection();
try
{
command.CommandText = "exec GetCourseCompletions #tmpCourse = '" + tmpCourse + "'";
SqlDataAdapter dataAdapter = new SqlDataAdapter(command);
dataAdapter.Fill(dataTable);
return dataTable;
}
catch (Exception)
{
throw new Exception("There are no VG's for this course.");
}
finally
{
command.Connection.Close();
}
}
And here is my stored procedure.
create procedure GetCourseCompletions
#tmpCourse nvarchar(30)
as
select (count(pnr) * 100 / (select count(pnr)
from HasStudied
where courseCode = #tmpCourse
and count(pnr) =)) as VGPrecentage
from HasStudied
where grade >= 5
and courseCode = #tmpCourse
go
The problem is that if there are no students with a high pass I will get a divide by zero exception. Looking for suggestions on how to catch this exception so the program does not crash or even better to re-write the stored procedure so it does not get an exception in the first place.
Thank you for your assistance!
Do what Eric said:
DECLARE #count int
Set #count = (select count(pnr) from HasStudied where courseCode = #tmpCourse and count(pnr) =...)
IF #count = 0
BEGIN
SELECT 0 as VGPrecentage
END
ELSE
BEGIN
select (count(pnr)*100 / #count) as VGPrecentage from HasStudied where grade >= 5 and courseCode = #tmpCourse
END
I suggest you to use this kind of query instead of yours that will handle NULL values and Zero values:
SELECT
CASE WHEN part * total <> 0 THEN part * 100 / total ELSE 0 END
FROM (
SELECT SUM(CASE WHEN grade > 5 THEN 1.00 ELSE 0.00 END) As part, SUM(1.00) as total
FROM HasStudied
WHERE courseCode = #tmpCourse) t
My sql table contains date of birth of many people.dates are in mm/dd/yyyy format. I want select the persons details whose birth day in next 30days. And i use the following query for that,
SELECT Mem_FirstNA, Mem_LastNA, Mem_DOB FROM MemberDetails WHERE
ltrim(str(year(GETDATE()))) + -' + ltrim(str(month(Mem_DOB))) + '-' +
ltrim(str(day(Mem_DOB))) >= getdate() - 1 AND
ltrim(str(year(GETDATE()))) + '-' + ltrim(str(month(Mem_DOB))) + '-' +
ltrim(str(day(Mem_DOB))) <= getdate() + 30
And full code is
public List<MemberData> GetThisMonthBirthday()
{
List<MemberData> MD = new List<MemberData>();
using (SqlConnection con = new SqlConnection(Config.ConnectionString))
{
using (SqlCommand cmd = new SqlCommand("SELECT Mem_FirstNA, Mem_LastNA, Mem_DOB FROM MemberDetails WHERE ltrim(str(year(GETDATE()))) + '-' + ltrim(str(month(Mem_DOB))) + '-' + ltrim(str(day(Mem_DOB))) >= getdate() - 1 AND ltrim(str(year(GETDATE()))) + '-' + ltrim(str(month(Mem_DOB))) + '-' + ltrim(str(day(Mem_DOB))) <= getdate() + 30", con))
{
try
{
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
MemberData mb = new MemberData();
mb.Mem_NA = (string)reader["Mem_FirstNA"];
mb.Mem_LastNA =(string)reader["Mem_LastNA"];
mb.Mem_DOB = (Convert.ToDateTime(reader["Mem_DOB"]));
MD.Add(mb);
}
}
catch (Exception e) { throw e; }
finally { if (con.State == System.Data.ConnectionState.Open) con.Close(); }
return MD;
}
}
The problem is that this check only till December 31, if the persons birthday in 01/01/1987 , the query is not selected that details. Please help me to solve this problem. Thank you
There are lots of ways to do this, you need conditional logic depending on whether or not you are within 30 days of the end of the year. If you're using SQL Server, I'd wrap the logic in a function to make it more readable, e.g.:
CREATE FUNCTION [dbo].[IsBirthdayInRange]
(
#Birthday DATETIME,
#StartDate DATETIME,
#EndDate DATETIME
)
RETURNS BIT
AS
BEGIN
DECLARE #StartMonthDay INT
DECLARE #EndMonthDay INT
DECLARE #BirthdayMonthDay INT
SET #StartMonthDay = MONTH(#StartDate) * 100 + DAY(#StartDate)
SET #EndMonthDay = MONTH(#EndDate) * 100 + DAY(#EndDate)
SET #BirthdayMonthDay = MONTH(#Birthday) * 100 + DAY(#Birthday)
IF YEAR(#StartDate) <> YEAR(#EndDate)
BEGIN
IF #BirthdayMonthDay >= #StartMonthDay OR #BirthdayMonthDay <= #EndMonthDay
BEGIN
RETURN 1
END
END
ELSE
BEGIN
IF #BirthdayMonthDay >= #StartMonthDay AND #BirthdayMonthDay <= #EndMonthDay
BEGIN
RETURN 1
END
END
RETURN 0
END
You can then use it as:
...
WHERE IsBirthdayInRange(Mem_DOB, GETDATE(), GETDATE() + 30)
I have a DATETIME column in my database. I need to get the value and divide it into 3 variables each having the year, month and day
I am trying to do
dataadapter.Fill(dataset, "tablename");
string x;
foreach(DataRow dd in dataset.Tables["tablename"].Rows)
{
x = dataset.Tables["tablename"].Rows[0]["date1"].ToString();
}
here x is holding the whole of m/dd/yr and time but how can I now have 3 variables which can store the month in a, year in b and day in another variable c?
How about this.
int year, month, day;
DateTime all;
if(DateTime.TryParse(dataset.Tables["tablename"].Rows[0]["date1"], out all)
{
year = all.Year;
month = all.Month;
day = all.Day;
}
foreach(DataRow dd in dataset.Tables["tablename"].Rows)
{
var date = DateTime.Parse(dd["date1"].ToString());
int day = date.Day;
int month = date.Month;
int year = date.Year;
// Do something with it
}
DateTime dt = DateTime.Parse(x);
int day = dt.Day;
int month = dt.Month;
int year = dt.Year;
DateTime x;
foreach(DataRow dd in dataset.Tables["tablename"].Rows)
{
x = DateTime.Parse(dataset.Tables["tablename"].Rows[0]["date1"].ToString());
}
Then you don't need to keep 3 separate variables, you'll have x as a DateTime so you can just call x.Year, x.Month, x.Date (You could still assign it to 3 different variables if you want)
I guess that the best way would be to create a SQL query that will get desired date components for you, then fill the datatable from that query, not from the table itself.
That way, you'll learn some SQL date handling functions by the way... :)
What is the datatype of the field in the database?
If your database field is a string then you'll have to parse it, otherwise you can just cast it to a DateTime:
// Parse it (be careful, could throw an exception)
DateTime date = DateTime.Parse(dataset.Tables["tablename"].Rows[0]["date1"].ToString());
// Or cast it:
DateTime date = (DateTime)dataset.Tables["tablename"].Rows[0]["date1"];
// Then pull out the values you wish to use from the date object
int months = date.Month;
int day = date.Day;
int year = date.Year;
Some options:
You can bust it up into its component parts in SQL:
select yyyy = year( t.some_datetime ) , -- integer year
mm = month( t.some_datetime ) , -- integer month (1-12)
dd = day( t.some_datetime ) , -- integer day (1-31)
from dbo.some_table t
You can convert it a fixed length ISO 8601 string (easy to parse, collates properly), again in SQL:
select charDate = convert(char(10),t.some_datetime,126) -- 'yyyy-mm-dd'
from dbo.some_table t
Parsing out the components is an easy substring operation.
As noted by others: Just select the datetime value. ADO.Net maps that to System.DateTime.
using System;
using System.Data;
using System.Data.SqlClient;
namespace ConsoleApplication4
{
class Program
{
static void Main( string[] args )
{
string myConnectString = GetConnectionString() ; // your connect string here!
using ( SqlConnection dbConnection = new SqlConnection( myConnectString ) )
using ( SqlCommand sql = dbConnection.CreateCommand() )
{
sql.CommandType = CommandType.Text ;
sql.CommandText = #"
select t.some_datetime
from dbo.some_table t
" ;
dbConnection.Open() ;
using ( SqlDataReader reader = sql.ExecuteReader() )
{
while ( reader.Read() )
{
DateTime someDateTime = reader.GetDateTime(0) ;
process( someDateTime.Year , someDateTime.Month , someDateTime.Day ) ;
}
}
dbConnection.Close() ;
}
return ;
}
private static void process( int p , int p_2 , int p_3 )
{
throw new NotImplementedException();
}
}
}