I want to make passive them if a date is earlier than today from the recorded dates within database with update command.How can I do that by using single query in C#?
Colums: Tarih(nvarchar) , Durum(nvarchar)
For example;
if tarih<Datetime.Today.Date is set Durum='PASİF'
Code:
string sorgu = "select BitTarihi from Abonelikler";
SqlConnection gg = new SqlConnection(constr);
SqlCommand gg2 = new SqlCommand(sorgu,gg);
SqlDataReader gg3;
gg.Open();
gg3= gg2.ExecuteReader();
while (gg3.Read())
{
DateTime b1 = new DateTime();
DateTime b2 = new DateTime();
b1 = Convert.ToDateTime(gg3.GetString(0));
b2 = DateTime.Today.Date;
TimeSpan fark = new TimeSpan();
fark = b2 - b1;
if (fark.TotalDays > 0)
{
SqlConnection vv = new SqlConnection(constr);
SqlCommand vv2 = new SqlCommand("update Abonelikler set Durum='PASİF' where BitTarihi='" + b1.ToShortDateString() + "'", vv);
vv.Open();
vv2.ExecuteNonQuery();
vv.Close();
vv2.Dispose();
}
}
gg.Close();
gg2.Dispose();
Look at DATEDIFF function.
UPDATE Abonelikler SET Durum='PASIF'
WHERE DATEDIFF(DD, CONVERT(datetime, BitTarihi), GETDATE())>0
Also, please do not use concatenation of an SQL statement, use parameters. It's more safe and also sometimes concatenation of statement with parameters hampers server-side statement optimization.
Instead of updating the records why don't you decide the state at query level? Since you check this everyday there will be many unneeded updates.
SELECT BitTarihi, CASE WHEN DATEDIFF(DAY, BitTarihi, GetDate()) = 0 THEN 'AKTIF' ELSE 'PASIF' END DURUM FROM Abonelikler
This way you won't have to update your records.
Related
I have a table of data in Access
DateTimeLog has date/time datatype while the other rest are string.
I need to get the total number of row of data at the last hour of system date with specified ModelLog. But I could not think of a correct structure of the query using MS Access as I am very new to MS Access.
Below shows how I insert the data:
DateTime now = DateTime.Now;
var today = now.ToString("g");
DateTime d = DateTime.Parse(today);
const string sql = #"INSERT INTO timer(DateTimeLog, ShiftLog, CTLog, WorkcellLog, ModelLog, StationLog)VALUES(#d, #shift, #ct, #wc, #wm, #ws)";
OleDbCommand cmd = new OleDbCommand(sql, connection);
cmd.Parameters.Add("#d", OleDbType.DBTimeStamp).Value = d;
cmd.Parameters.Add("#shift", OleDbType.VarChar).Value = shiftlb.Text;
cmd.Parameters.Add("#ct", OleDbType.VarChar).Value = timerlb.Text;
cmd.Parameters.Add("#wc", OleDbType.VarChar).Value = wclb.Text;
cmd.Parameters.Add("#wm", OleDbType.VarChar).Value = mlb.Text;
cmd.Parameters.Add("#ws", OleDbType.VarChar).Value = slb.Text;
try
{}
catch(exception e)
{}
Ok, so you clearly know how to run a database query with parameters, you just need to run this query as ExecuteScalar, casting the result to an int
SELECT COUNT(*) FROM timer WHERE dateTimeLog >= #d
And then set your d parameter to an hour ago
cmd.Parameters.Add("#d", OleDbType.Date).Value = DateTime.Now.AddHours(-1);
Side note I would recommend not round tripping via string just to cut the seconds off a time. Instead consider:
var d = DateTime.Now;
d = d.AddTicks( -(d.Ticks % (60*TimeSpan.TicksPerSecond)));
Or maybe
var d = DateTime.Now;
d = d.AddMilliseconds(-d.Milliseconds).AddSeconds(-d.Seconds);
I found out another way of getting the number of data within the same hour. Create two new columns, HourID and TodayDate both represent current hour in 24hours format and today's date respectively. Insert the data accordingly.
Getting count of data:
const string sql = #"SELECT COUNT(*) FROM timer WHERE HourID = #h AND TodayDate = #td AND ModelLog = #m";
OleDbCommand cmd = new OleDbCommand(sql, connection);
cmd.Parameters.Add("#h", OleDbType.VarWChar).Value = DateTime.Now.ToString("%H");
cmd.Parameters.Add("#td", OleDbType.VarWChar).Value = DateTime.Now.ToShortDateString();
cmd.Parameters.Add("#m", OleDbType.VarWChar).Value = mlb.Text;
How do I compare a SQL Server DATETIME with the DateTime.Now value? As you can see I assigned it to a Session and tried comparing it with DateTime.Now.
string timestamp = #"SELECT sr.*, ud.* FROM SuspensionRecord sr, UserData ud WHERE sr.User_ID=#User_ID AND ud.User_ID=#User_ID";
using (SqlCommand cmd2 = new SqlCommand(timestamp, con))
{
cmd2.Parameters.AddWithValue("#User_ID", Session["UserID"].ToString());
using (SqlDataReader dr = cmd2.ExecuteReader())
{
if (dr.HasRows)
{
while (dr.Read())
{
Session["suspensiondate"] = dr["End_Date_Suspension"].ToString();
}
if (Convert.ToDateTime(Session["supensiondate"]) >= DateTime.Now.Date)
{
lblMessage.Text = "The account's status is suspended.";
lblMessage.Visible = true;
}
}
}
}
You should pass in the date and do the comparison in the query instead of in c#. That is one less step. If you do want to do it in c# then use the appropriate types, do not convert the DateTime to a string and then convert it back again.
There is no need for the join (2nd table) in your query
You do not have to use a DataReader for this, you can use ExecuteScalar which returns 1 value instead.
Use Add so you can specify the correct schema types with SqlDbType and not AddWithValue
string timestamp = #"SELECT 1 FROM SuspensionRecord sr WHERE sr.User_ID = #User_ID AND supensiondate > #now";
using (SqlCommand cmd2 = new SqlCommand(timestamp, con))
{
cmd2.Parameters.Add("#User_ID", SqlDbType.Int).Value = Session["UserID"]; // do not convert to string
cmd2.Parameters.Add("#now", SqlDbType.DateTime).Value = DateTime.Now.Date;
var result = cmd2.ExecuteScalar();
if(result != null) // if null then there were no records so account is not suspended
{
lblMessage.Text = "The account's status is suspended.";
lblMessage.Visible = true;
}
}
First, your SQL is terrible.
You are returning way too much data, and you are using an implicit join (when explicit joins are a part of ANSI-SQL for almost 30 years now!)
Second, Can we stop using AddWithValue() already?
Instead of all this code you can do the entire test on SQL and return a single value:
string sql =
#"SELECT CASE WHEN EXISTS
(
SELECT 1
FROM SuspensionRecord
WHERE User_ID = #User_ID
AND End_Date_Suspension >= CAST(GETDATE() AS DATE)
) THEN 1 ELSE 0 END";
Then you can use ExecuteScalar instead of ExecuteReader, and you don't need to loop through all the irrelevant data:
using (SqlCommand cmd2 = new SqlCommand(timestamp, con))
{
cmd2.Parameters.Add("#User_ID", SqlDbType.Int).Value = Session["UserID"];
if ((int)cmd2.ExecuteScalar() == 1)
{
lblMessage.Text = "The account's status is suspended.";
lblMessage.Visible = true;
}
}
I'm trying to return a query (in a gridview in ASP.NET) WHERE Time >= DateTime.Now.Add(-60). The WHERE clause has been giving me no end of difficulties.
DateTime pastTime = DateTime.Now.Add(-60);
ds_DB.SelectCommand = "SELECT * FROM [vPurchaseTotals] WHERE [TimeOfTransaction] >= " + pastTime;
My issue is getting pastTime to convert properly, so it only returns the newer data. [TimeOfTransaction] is a time(7) data type in the table.
How do I parse C#'s DateTime to SQL Server's Time?
Here, try this:
using(SqlConnection conn = new SqlConnection(yourConnectionString))
{
DateTime pastTime = DateTime.Now.Add(-60);
ds_DB.SelectCommand = #"SELECT * FROM [vPurchaseTotals]
WHERE [TimeOfTransaction] >= #PastTime";
SqlCommand cm = conn.CreateCommand();
cm.CommandText = ds_DB.SelectCommand;
cm.Parameters.Add("#PastTime", SqlDbType.Time).Value = pastTime.TimeOfDay; //For comparison with TSQL TIME type
try
{
conn.Open();
// Do what you need to do here.
}
catch(SqlException e)
{
// Handle Exception
}
finally
{
conn.Close();
}
}
Just for future reference, you should always parameterize your queries. It ends up being a lot safer and cleaner/easier to read and adjust.
EDIT: Are you using a SqlDataAdapter class? Is that what ds_DB is an instance of? I would personally just use a string value for your query and then implement the SqlDataAdapter like this:
try
{
conn.Open();
using(SqlDataAdapter da = new SqlDataAdapter(cm))
{
da.Fill(DataTable dt);
}
}
C#/MySQL - Set WinForm Access Date MySQL
So I created a MySQL Database which my form is able to access & login to. My goal for it is to be able to pull information from the MySQL Database into the form as a label (I know easy right?).
Example:
The hardest problem for me was figuring out how to store lets say a "Subscription" start/end date and be able to tell me on a label, how many days I had left on my subscription. All this using information for the database.
(Yes this database is for test purposes only no where near final.)
Created a table called edata.
Created fields the program would use
(Account Status/StartSub/EndSub)
My Question: How would I go about taking the dates entered and creating a value that I could use to show in the "Days Left Here" label?
I will create the table like this:
CREATE TABLE `test`.`New Table` (
`ID` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
`FirstName` VARCHAR(45),
`LastName` VARCHAR(45),
`Username` VARCHAR(45),
`Password` VARCHAR(45),
`Account` INTEGER UNSIGNED,
`StartSub` DATETIME,
`EndSub` DATETIME,
PRIMARY KEY (`ID`)
)
ENGINE = InnoDB;
Then query like this:
using (MySqlConnection conn = new MySqlConnection(constring))
{
using (MySqlCommand cmd = new MySqlCommand())
{
cmd.Connection = conn;
conn.Open();
cmd.CommandText = "select * from edata where id = 1;";
MySqlDataAdapter da = new MySqlDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
conn.Close();
DateTime dateStart = Convert.ToDateTime(dt.Rows[0]["StartSub"]);
DateTime dateEnd = Convert.ToDateTime(dt.Rows[0]["EndSub"]);
if (DateTime.Now >= dateStart && DateTime.Now <= dateEnd)
{
TimeSpan ts = dateEnd - DateTime.Now;
label1.Text = "Active";
label2.Text = ts.TotalDays + " day(s) left";
}
else
{
label1.Text = "Expired";
label2.Text = "0 day left";
}
}
}
If you can parse the values out it is pretty simple, for example:
string end_date_string = "2014-09-24";
string start_date_string = "2014-09-18";
DateTime end_date = DateTime.Parse(end_date_string); // parse end date
DateTime start_date = DateTime.Parse(start_date_string); // parse start date
TimeSpan dur = end_date.Subtract(start_date); // total duration
TimeSpan timeleft = end_date.Subtract(DateTime.Now); // how much time left until we hit the end_date
Label l;
l.Text = timeleft.Days.ToString();
// l.Text = timeLeft.Hours.ToString();
// l.Text = timeleft.Minutes.ToString();
I have a talent table holding all my users with a column holding their birthdays. what would be the best way Talent within a specified age range. Here's what I have, but is seems to be off by a couple days. is there a better way?
// BUILD SQL FROM FORM DATA
sqlString += "SELECT * from Talent";
if (minAge != 0 || maxAge != 120)
{
// The age criteria has been change, filter by age.
// select all talents that have birthdays between the following 2 dates.
DateTime startDate = (DateTime.Now - new TimeSpan((maxAge * 365), 0, 0, 0)); // maxAge * 365 = totalDays
DateTime endDate = (DateTime.Now - new TimeSpan((minAge * 365), 0, 0, 0));
sqlString += " WHERE Birthdate BETWEEN '" + startDate.ToString() + "' AND '" + endDate.ToString() + "'";
}
Assuming you're using SQL Server...
using (var connection = new SqlConnection(connString))
using (var command = connection.CreateCommand()) {
string tsql = #"
select *
from Talent
where DATEDIFF(YEAR, BirthDay, GETDATE()) BETWEEN #minAge AND #maxAge";
command.CommandText = tsql;
command.CommandType = CommandType.Text;
int minAge = 1;
int maxAge = 120;
SqlParameter minAgeParam = command.CreateParameter();
minAgeParam.Direction = ParameterDirection.Input;
minAgeParam.DbType = SqlDbType.TinyInt;
minAgeParam.ParameterName = "#minAge";
minAgeParam.Value = minAge;
SqlParameter maxAgeParam = command.CreateParameter();
maxAgeParam.Direction = ParameterDirection.Input;
maxAgeParam.DbType = SqlDbType.TinyInt;
maxAgeParam.ParameterName = "#maxAge";
maxAgeParam.Value = maxAge;
// Just unsure here whether I must add the parameters to the command,
// or if they are already part of it since I used the
// SqlCommand.CreateParameter() method.
// Been too long since I haven't done any ADO.NET
command.Parameters.Add(minAgeParam);
command.Parameters.Add(maxAgeParam);
connection.Open();
SqlDataReader reader = null;
try {
reader = command.ExecuteReader();
// Process your records here...
} finally {
connection.Close()
command.Dispose();
connection.Dispose();
if (reader != null) {
reader.Dispose();
}
}
}
Where #minAge and #maxAge are your age parameters.
You may also tell the DATEDIFF TSQL function to consider the difference in days, in month, in hours, in minutes, in seconds, etc. Hence, you will have to convert your parameters value accordingly.
Personally, I've found using startDate.ToString("yy-MM-dd 00:00:00.000") and endDate.ToString("yy-MM-dd 23:59:59.000") works best (note the ,000 on the end date range. For some reason, in my experience, sql is off (probably due to some kind of rounding error) when it comes to ranges.
As an aside, you can use static methods from the TimeSpan object for time calculations. e.g. TimeSpan.FromDays(...)
The problem might be related to DateTime.Now, which considers time as well as date. Try replacing it with a DateTime.Today.
Why don't you use DateTime.AddYears method.
DateTime startDate = DateTime.Now.AddYears(-maxAge);
insated of
DateTime startDate = (DateTime.Now - new TimeSpan((maxAge * 365), 0, 0, 0));
Another thing is: Please don't use + operator between strings to build a sql query, use StringBuilder instead.
For what it's worth - your original solution is off by a few days because it is using 365 instead of accounting for leap years.