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.
Related
Instead of using:
int noOfDaysInMonth = DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month);
I want to use the 2 values passed in to get number of days in a month:
public ActionResult Index(int? month, int? year)
{
DateTime Month = System.Convert.ToDateTime(month);
DateTime Year = System.Convert.ToDateTime(year);
int noOfDaysInMonth = DateTime.DaysInMonth(Year, Month);
(Year, Month) is flagging as invalid arguments? any ideas? maybe system.conert.todatetime.month?
They are DateTime variables but DaysInMonth needs ints:
int noOfDaysInMonth = DateTime.DaysInMonth(year.Value, month.Value);
If they can be null:
int noOfDaysInMonth = -1;
if(year != null && month != null)
noOfDaysInMonth = DateTime.DaysInMonth(year.Value, month.Value);
There is no overload for the DateTime.DaysInMonth method that takes two DateTime instances. Instead of creating those two DateTime instances, just pass the parameters you received directly to DaysInMonth.
Notice that method can't take null values, so either drop the nullables or sanitize your input, i.e.: check if the year and month are null, and if they are, use some default value instead.
DateTime.DaysInMonth takes int parameter and not date time parameter
public static int DaysInMonth(
int year,
int month
)
Beware though, you are passing in nullable int's. So check before if they have value
if(month.HasValue && year.HasValue)
{
var numOfDays = DaysInMonth(year.Value, month.Value);
}
You don't need to use any DateTime object here, but you need to validate the input!
public ActionResult Index(int? month, int? year)
{
int noOfDaysInMonth = -1;
if(year.HasValue && year.Value > 0 &&
month.HasValue && month.Value > 0 && month.Value <=12)
{
noOfDaysInMonth = DateTime.DaysInMonth(year.Value, month.Value);
}
else
{
// parameters weren't there or they had wrong values
// i.e. month = 15 or year = -5 ... nope!
noOfDaysInMonth = -1; // not as redundant as it seems...
}
// rest of code.
}
The if works because conditions are evaluated from left to right.
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.
In my system ,the due date of the bill must be 14 days after the issued date.
I have due date and I want to know issued date .
I have to calculate :
issued date = 14 days prior to the due date
but 14 days must be business days ,not holidays.
Holidays is stored in a table 'tblHolidayMaster' like this,
Date Description
2012/05/13 Mother's
Day2012/06/02 Saturnday2012/12/25 Christmas
How can I calculate the issued date avoiding holidays?
Thank you for all of your interests and replies.
I would calculate the Date using a function like the one below (which i use)
public static DateTime AddBusinessDays(DateTime date, int days)
{
if (days == 0) return date;
if (date.DayOfWeek == DayOfWeek.Saturday)
{
date = date.AddDays(2);
days -= 1;
}
else if (date.DayOfWeek == DayOfWeek.Sunday)
{
date = date.AddDays(1);
days -= 1;
}
date = date.AddDays(days / 5 * 7);
int extraDays = days % 5;
if ((int)date.DayOfWeek + extraDays > 5)
{
extraDays += 2;
}
int extraDaysForHolidays =-1;
//Load holidays from DB into list
List<DateTime> dates = GetHolidays();
while(extraDaysForHolidays !=0)
{
var days = dates.Where(x => x >= date && x <= date.AddDays(extraDays)).Count;
extraDaysForHolidays =days;
extraDays+=days;
}
return date.AddDays(extraDays);
}
Haven't tested the ast section that does the holidays
I went with the straight forward looping solution, so it will be slow for long intervals. But for short intervals like 14 days, it should be quite fast.
You need to pass in the holidays in the constructor. An instance of BusinessDays is immutable and can be reused. In practice you probably will use an IoC singleton or a similar construct to get it.
AddBusinessDays throws an ArgumentException if the start date is a non business day, since you didn't specify how to treat that case. In particular AddBusinessDays(0) on a non business day would have strange properties otherwise. It'd either break time reversal symmetry, or return a non business day.
public class BusinessDays
{
private HashSet<DateTime> holidaySet;
public ReadOnlyCollection<DayOfWeek> WeekendDays{get; private set;}
public BusinessDays(IEnumerable<DateTime> holidays, IEnumerable<DayOfWeek> weekendDays)
{
WeekendDays = new ReadOnlyCollection<DayOfWeek>(weekendDays.Distinct().OrderBy(x=>x).ToArray());
if(holidays.Any(d => d != d.Date))
throw new ArgumentException("holidays", "A date must have time set to midnight");
holidaySet = new HashSet<DateTime>(holidays);
}
public BusinessDays(IEnumerable<DateTime> holidays)
:this(holidays, new[]{DayOfWeek.Saturday, DayOfWeek.Sunday})
{
}
public bool IsWeekend(DayOfWeek dayOfWeek)
{
return WeekendDays.Contains(dayOfWeek);
}
public bool IsWeekend(DateTime date)
{
return IsWeekend(date.DayOfWeek);
}
public bool IsHoliday(DateTime date)
{
return holidaySet.Contains(date.Date);
}
public bool IsBusinessDay(DateTime date)
{
return !IsWeekend(date) && !IsHoliday(date);
}
public DateTime AddBusinessDays(DateTime date, int days)
{
if(!IsBusinessDay(date))
throw new ArgumentException("date", "date bust be a business day");
int sign = Math.Sign(days);
while(days != 0)
{
do
{
date.AddDays(sign);
} while(!IsBusinessDay(date));
days -= sign;
}
return date;
}
}
I think that is what you required. It is simple and I have tested it and it is working... And it is not a bad approach to write a function or SP in databases rather to write the complex code in C#... (change column name of date as in your db.)
Make it function or SP as what you want.
Note: Comment the check of 'Saturday' and 'Sunday'. If it is already added in your table reocrds.
declare #NextWorkingDate datetime
declare #CurrentDate datetime
set #CurrentDate = GETDATE()
set #NextWorkingDate = #CurrentDate
declare #i int = 0
While(#i < 14)
Begin
if(((select COUNT(*) from dbo.tblHolidayMaster where convert(varchar(10),[Date],101) like convert(varchar(10),#NextWorkingDate,101)) > 0) OR DATENAME(WEEKDAY,#NextWorkingDate) = 'Saturday' OR DATENAME(WEEKDAY,#NextWorkingDate) = 'Sunday')
Begin
print 'a '
print #NextWorkingDate
set #NextWorkingDate = #NextWorkingDate + 1
CONTINUE
End
else
Begin
print 'b '
print #NextWorkingDate
set #NextWorkingDate = #NextWorkingDate + 1
set #i = #i + 1
CONTINUE
End
End
print #NextWorkingDate
I calculate the issued date avoid your holiday from your table 'tblHolidayMaster' only.
int addDay = -14;
DateTime dtInputDay = System.DateTime.Now;//Your input day
DateTime dtResultDate = new DateTime();
dtResultDate = dtInputDay.AddDays(addDay);
bool result = false;
string strExpression;
DataView haveHoliday;
while (!result) {
strExpression = "Date >='" + Convert.ToDateTime(dtResultDate.ToString("yyyy/MM/dd")) + "' and Date <='" + Convert.ToDateTime(dtInputDay.ToString("yyyy/MM/dd")) + "'";
haveHoliday = new DataView(tblHolidayMaster);
haveHoliday.RowFilter = strExpression;
if (haveHoliday.Count == 0) {
result = true;
} else {
addDay = -(haveHoliday.Count);
dtInputDay = dtResultDate.AddDays(-1);
dtResultDate = dtResultDate.AddDays(addDay);
}
}
Your issued date is dtResultDate
Try the following link,
http://www.c-sharpcorner.com/uploadfile/tirthacs/difference-between-two-dates-excluding-weekends/
I have file names like: abc 99 rep_DD_MM_YYYY_file_v-X.XX.zip where DD_MM_YYYY is date and X.XX is the version. (eg. abc 99 rep_01_01_2012_file_v-1.00).
I need to compare in C# or SQL Server the two strings:
abc 99 rep_DD_MM_YYYY_file_v-X.XX.zip
abc 99 rep_01_01_2012_file_v-1.00
get extract of the values of the position DD, MM, YYYY & XXX of the 2nd string and then arrange them into YYYYMMDDXXX format to compare which one is the latest one.
Please can any one suggest me how can I do this comparison in C# or T-SQL ?
You'll need to parse the DateTime from both strings with DateTime.ParseExact
It could be done with regex. Since I really suck with regex, I will propose another way:
var day = fileName.SubString(11,2);
var month = fileName.SubString(14,2);
var year = fileName.SubString(17,4);
var version = fileName.SubString(29,4);
var result = String.Concat(year,month,day,version);
declare #filename varchar(50)
set #filename = 'abc 99 rep_01_01_2012_file_v-1.00'
declare #date varchar(10)
select #date = substring(#filename, 12, 10)
select #date
declare #xxx varchar(10)
select #xxx = replace(right(#filename,4),'.','')
select #xxx
select right(#date,4) + right(left(#date,5),2) + left(#date,2) + #xxx
The position of "DD", "YYYY / YY", "MM / MMM" may vary. So I need more complex date parser.
The parser I'm using now:
public void Main()
{
string name = "bmsa1110_v1.1.zip";
string varPattern = "####YYMM##XXX####";
getVarPart(name, varPattern);
}
private string getVarPart(string name, string varPattern)
{
StringBuilder name_sb = new System.Text.StringBuilder(name);
StringBuilder varPattern_sb = new System.Text.StringBuilder(varPattern);
string YEAR = null;
string MONTH = null;
string DAY = null;
string VERSION = null;
for (int j = 0; j < varPattern_sb.Length; j++)
{
switch (varPattern_sb[j])
{
case 'Y':
YEAR = YEAR + name_sb[j];
name_sb[j] = '#';
break;
case 'M':
MONTH = MONTH + name_sb[j];
name_sb[j] = '#';
break;
case 'D':
DAY = DAY + name_sb[j];
name_sb[j] = '#';
break;
case 'X':
VERSION = VERSION + name_sb[j];
name_sb[j] = '#';
break;
default:
break;
}
}
string varPart = YEAR + MONTH + DAY + VERSION;
return varPart;
}
Though, Thanks all for your answer. If you have any suggestion, please share..
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();
}
}
}