How to properly convert query into DateTime in asp.net? - c#

In my app, I am trying to grab a date from the database and compare it against local time. Right now I am getting an error when I am converting to date incorrectly.
I have tried:
Convert.ToDateTime()
DateTime.ParseExact()
My code:
string time = "Select top(1) DATE from SERVICE order by DATE desc";
SqlCommand command = new SqlCommand(time, connection);
connection.Open();
using (SqlDataReader timereader = timecommand.ExecuteReader())
{
while (timereader.Read())
{
if (DateTime.ParseExact(time, "yyyy-MM-dd HH:mm:ss", null).AddMinutes(10) > currenttime)
{
// code
}
}
connection.Close();
}
I am hoping when I retrieve this value from the database, I can convert it into a proper datetime value and compare against local time and run other code after that.
At the moment I am just getting this error:
The string was not recognized as a valid DateTime. There is an unknown word starting at index 0.
I'm probably just dumb and missing something obvious..

Your query selects a single value. Use ExecuteScalar and cast it to a DateTime (it's already a DateTime, but boxed inside an object):
string time = "Select top(1) DATE from SERVICE order by DATE desc";
SqlCommand command = new SqlCommand(time, connection);
connection.Open();
DateTime d = (DateTime)command.ExecuteScalar();
connection.Close();
After you do this, and before you embark on some long mission of this protracted way of getting data out of a database, converting it to objects for use in your app etc, take a look at least at an ORM called Dapper, if not Entity Framework. Dapper's basically what you're doing now, but it auto converts your queries to objects and back and saves a lot of tedious code. With Dapper it'd look more like:
using (var connection = new SqlConnection("connstr"))
{
var d = connection.QuerySingle<DateTime>("SELECT TOP 1 Date FROM ...");
}
Yes, it's not much of a saving over what you have now, right? But what if you have a list of Order that themselves have 20 properties:
using (var connection = new SqlConnection("connstr"))
{
var orders = connection.Query<Order>("SELECT * FROM order WHERE customerID = #custid", new {custid = 123}).ToList();
}
Orders is now a list of Order objects for customer 123, parameterized, injection safe, quick and a one liner to read and populate your orders; doing that in a datareader is going to take at least 25 lines of boring code
http://dapper-tutorial.net and spend 2 minutes reading; I'll lay bets you'll be glad you did

Just try to read the value as a proper, native DateTime type like this (assuming that the DATE column in SQL Server is in fact a DATETIME or similar datatype - not a string - hopefully!):
using (SqlDataReader timereader = timecommand.ExecuteReader())
{
while (timereader.Read())
{
// just read the DateTime value as such
DateTime dt = timereader.GetDateTime(0);
// then do whatever you need to do with this DateTime value .....
}
connection.Close();
}

Related

C# changing date format from SQL Server

I'm relatively new to C#, SQL Server, and Stackoverflow.
I want the format of my date to stay the same from SQL Server to my C# code.
I have a screenshot of the SQL Server table:
.
I just want the format to stay the same. I want the format to stay yyyy-mm-dd instead when I retrieve the data the format is dd/mm/yyyy 0:00:00.
I then use the following code to retrieve the data from the server:
ArrayList a = new ArrayList();
DataTable d = new DataTable();
string sql = "SELECT * FROM myServer";
MySql.Data.MySqlClient.MySqlCommand cmd = new MySql.Data.MySqlClient.MySqlCommand(sql, conn);
MySqlDataAdapter myA = new MySqlDataAdapter(cmd);
myA.Fill(d);
cmd.ExecuteNonQuery();
foreach (DataRow row in d.Rows)
{
FitnessManager f = new FitnessManager();
f.testDate = row["testDate"].ToString();
f.tDate = row["tDate"].ToString();
f.dtDate = row["dtDate"].ToString();
a.Add(f);
}
return a;
I would expect the results in the ArrayList to be 2020-10-13, instead I'm getting 10/11/2020 0:00:00.
I do not know why this happens for how to fix this.
You would do something like this:
f.tDate = row["tDate"].ToString("yyyy-MM-dd")
The ToString() function accepts a format string, so you can pretty much convert it to whatever format you want.
More information here:
https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings
I found a previous post that helped me out a lot.
Change date format in C# when reading from database and setting to label
I needed to specify that the data being formatted was datatime rather than ToString() being called as an object.
Thanks E.J for putting me on the right track.

How do I insert multiple rows into MySql using C# where columns have dates?

The following class captures SendQueue objects from API json responses:
public class SendQueue
{
public DateTime SendDate { get; set; }
public int StatusCode { get; set; }
public string StatusMessage { get; set; }
}
When I receive the object, I convert the SendDate value to string to insert into a MySQL database, but the formatting apparently is not accepted by the DB and so the insert fails.
When I convert the value to string, the formatting of the SendDate is "dd/MM/yyyy hh:mm:ss" whereas the database accepts "yyyy-MM-dd hh:mm:ss".
Of course, a better way of handling this is via parameterized queries. But since I am using batch inserts, I am unable to use DateTime objects.
INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);
I will have the same problem if I use Bulk Insert as well since the dates will eventually be converted to strings stored in a file.
You should use an appropriate DateTime type in your schema. Do not use strings to represent Dates or DateTimes or Times, numbers, or anything else that is not a native string.
MySql allows for the following schema types:
DATE
TIME
DATETIME
TIMESTAMP
YEAR
In this case the most appropriate one would be DATETIME. This aligns with the .net type System.DateTime. If you are using ADO.NET then you should be using parameters in your queries. Example:
using(MySqlCommand m = new MySqlCommand("INSERT INTO table (sendDate) VALUES (#sendDate)"))
{
m.Parameters.Add("#sendDate", MySqlDbType.DateTime).Value = myObj.SendDate;
// rest of code
}
Batch Insert
You do not have to run one insert statement at a time. You can easily create one statement with multiple tuples that you want to insert. Here is sample c# code that does that with 1 column. You can easily extend this with multiple values per tuple.
var sql = "INSERT INTO table (sendDate) VALUES (";
var parameters = input.Select((queue, i) => new MySqlParameter("#sendDate" + i.ToString(), MySqlDbType.DateTime)).ToArray();
sql += string.Join("), (", parameters.Select(_ => _.ParameterName)) + ")";
for (int i = 0; i < parameters.Length; i++)
{
parameters[i].Value = input[i].SendDate;
}
using(var connection = new MySqlConnection(connectionString))
using(var command = new MySqlCommand(sql, connection))
{
command.Parameters.AddRange(parameters);
connection.Open();
command.ExecuteScalar();
}
When to convert?
The code stack should always convert a DateTime to a string as late as possible up the call stack, generally in the Presentation Layer (at the point a Human has to read it). The reverse is also true, a string input should be converted to a DateTime as early as possible going down the call stack (so again, in the presentation layer).
Why not varchar for Dates?
If you are wondering why you should not store DateTime as a string see this previous answer: When to use VARCHAR and DATE/DATETIME. I'll quote the important stuff:
Some of the disadvantages of the VARCHAR version:
You can't easily add / subtract days to the VARCHAR version.
It is harder to extract just month / year.
There is nothing stopping you putting non-date data in the VARCHAR column in the database.
The VARCHAR version is culture specific.
You can't easily sort the dates.
It is difficult to change the format if you want to later.
It is unconventional, which will make it harder for other developers to understand.
In many environments, using VARCHAR will use more storage space. This may not matter for small amounts of data, but in commercial environments with millions of rows of data this might well make a big difference.
Time Zones and Values
Do not forget about time zones if this is applicable to your application. It is recommended to always store a DateTime UTC value in the database instead of a local timezone value. The UTC value can then be sent to the presentation layer where the presentation layer is responsible for applying the local time zone to the value (optional). Some UI frameworks have built in mechanisms for doing this in the DateTime controls. Again, the reverse is also true, have the presentation layer convert any input to a UTC DateTime value and send that back down the call stack to the server.
Per your updated question, it seems the root issue is that you need a way to insert multiple rows via a single insert statement.
Ideally you'd provide a stored procedure which could accept a table type as input, as could be done in the SqlServer world: Insert entire DataTable into database at once instead of row by row?
Given that's not an option for MySQL at time of writing however, there are a few alternatives...
If you need to do this because you need all rows to be inserted in the same transaction, simply wrap your inserts in a transaction. Code would be something like this (untested as I don't have MySQL).
public void InsertMySql(string connectionString, string command, DataTable data)
{
using (var connection = new MySqlConnection(connectionString))
{
connection.Open();
using (var transaction = connection.BeginTransaction())
{
try
{
using (MySqlCommand cmd = new MySqlCommand(command, connection))
{
cmd.CommandType = CommandType.Text;
foreach (var row in data.Rows)
{
cmd.Parameters.Clear();
foreach (var cell in data.Columns)
{
cmd.Parameters.AddWithValue($"#{cell.Name}", row[cell]);
}
cmd.ExecuteNonQuery();
}
}
transaction.Commit();
}
catch
{
transaction.Rollback();
throw;
}
}
}
}
If you need to do this for performance reasons, another option may be to look into a third party library such as: https://github.com/zzzprojects/Bulk-Operations. I've not tried this personally, but the library looks promising / the publisher (zzzprojects) are quite well known and respected / maintain the popular site SQL Fiddle amongst other projects.
public static void InsertMySql(string connectionString, DataTable data)
{
using (var connection = new MySqlConnection(connectionString))
{
connection.Open();
var bulk = new BulkOperation(connection);
bulk.BulkInsert(data); //assumes your data table's table name, column names/definitions match your table's; I think. See https://bulk-operations.net/bulk-insert for what documentation's available
}
}

Passing C# datetime value to Oracle DB Query

I have a SQL query that I am passing a C# variable into my Oracle DB.
I am having trouble passing a C# datetime variable, "PROCESS_DATE", into my query in my application. I do not get any records back. If I copy the query into my oracle developer tool, TOAD, it works fine and I get multiple records.
Here is the query I am using in my application:
String SelectAllSQL = "SELECT * FROM REALMS_AUDIT.R2_GROUP_QUERY_RPT WHERE PROCESS_DATE = :pPROCESS_DATE";
I also tried converting the datetime variable into a shortDateString() so it matches the database exactly I then used the TO_DATE function, which I have to use if I query dates directly in TOAD, without any luck. The shortDateString() changes my date into: 1/16/2016, which is what I need, but the OracleDataReader does not like it. Here it the query with the TO_DATE function:
String SelectAllSQL = "SELECT * FROM REALMS_AUDIT.R2_GROUP_QUERY_RPT WHERE PROCESS_DATE = TO_DATE(:pPROCESS_DATE, 'MM-DD-YYYY'";
:pROCESS_DATE is a datetime variable that is passed in.
There must be a breakdown between C# and Oracle in relation to handling a datetime variable. I am using Oracle DataReader to handle the processing of the query.
OracleDataReader dataReader = mDataAccess.SelectSqlRows ( oracleConnection, oracleCommand, sqlCommand, parameters );
while ( dataReader.Read ( ) )
{
groupEntityFacilityRptList.Add ( ReadRecord ( dataReader ) );
}
If I use the TO_DATE function, the application will not step into the while loop. If I use the original query, it does but returns no data.
The datetime variable PROCESSDATE looks like this:
1/16/2016 12:00:00 AM
I notice it has a timestamp on it, so I'm not sure if that is the problem or not.
The data in Oracle is like this:
1/16/2016
Unless I've totally misunderstood your issue, I think you might be making this harder than it needs to be. ODP.net handles all of that dirty work for you. If PROCESS_DATE is an actual DATE datatype in Oracle, then you just need to pass an actual C# DateTime variable to it and let ODP.net do the heavy lifting. There is no need to do conversion of any type, provided you are passing an actual date:
DateTime testDate = new DateTime(2015, 7, 16);
OracleCommand cmd = new OracleCommand(
"SELECT * FROM REALMS_AUDIT.R2_GROUP_QUERY_RPT WHERE PROCESS_DATE = :pPROCESS_DATE",
conn);
cmd.Parameters.Add(new OracleParameter("pPROCESS_DATE", OracleDbType.Date));
cmd.Parameters[0].Value = testDate;
OracleDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
object o = reader.IsDBNull(0) ? null : reader.GetValue(0);
}
reader.Close();
If your data in C# is not a date, I'd recommend making it one before even trying:
DateTime testDate;
if (DateTime.TryParse(testDateString, out testDate))
{
// run your query
}
As per my comment, please try below and see this resolves.
TRUNC(TO_DATE(:pPROCESS_DATE,'MM-DD-YYYY HH:MI:SS AM')) if pROCESS_DATE format is 1/16/2016 12:00:00 AM.
TRUNC(TO_DATE(:pPROCESS_DATE,'DD-MM-YYYY HH:MI:SS AM')) if pROCESS_DATE format is 16/1/2016 12:00:00 AM.
First, I learned that my code will not go into the code below unless I actually have records returned to me.
OracleDataReader dataReader = mDataAccess.SelectSqlRows ( oracleConnection, oracleCommand, sqlCommand, parameters );
while ( dataReader.Read ( ) )
{
groupEntityFacilityRptList.Add ( ReadRecord ( dataReader ) );
}
Second, to get ProcessDate to work, I needed to take the string that was coming from my View, convert it to a datetime, and then I formatted it back as a string. It may not be best practices but it worked.
public JsonResult GetGroupReportData ( String reportDate )
{
DateTime processDate = DateTime.Parse ( reportDate );
var monthlyReport = SelectAllGroupRprt (processDate.ToString("MM/dd/yyyy");
return new JsonResult ( )
{
Data = monthly,
MaxJsonLength = Int32.MaxValue
};
}

Retrieving data from sqlite on the basis of date

I am retrieving data from Sqlite database using the following query in c#
SELECT * FROM tableName
It works fine. But I want to retrieve data on the basis of date like:
SELECT * FROM tableName WHERE date=09-09-2013
But it do not works for me because Sqlite date representation is not in this date format.
What i want to ask is that is there any method by which Sqlite data can be retrieved on the basis of user date and time like mentioned in above query and how can I represent date and time of Sqlite database in user readable format.
A parameterized query would free your code from the formatting required for date, strings and decimals by various database engines
using (SqliteConnection con = new SqliteConnection(connectionString))
{
con.Open();
string commandText = "SELECT * FROM tableName WHERE date=#dt";
using (SqliteCommand cmd = new SqliteCommand(commandText, con))
{
cmd.Parameters.AddWithValue("#dt", yourDateVariable)
SqliteReader reader = cmd.ExecuteReader();
while(reader.Read())
{
// Extract your data from the reader here
.....
}
}
}
The point of this example is to show how to build a parameterized query. In this way you pass the value of your datetime variable to the framework of Sqlite engine that knows better how to format a date for the underlying system.
In the commandText variable the actual formatted value for the date is taken by the placeholder #dt, then add, to the SqliteCommand Parameters collection, a parameter with the same name of the placeholder and the value from your date variable.

Finding time difference between two times stored in database using sql and c#

string sqlUserName3 = "SELECT out_date FROM status where s_id='" + TextBox2.Text + "'";
SqlCommand sqlcmd3 = new SqlCommand(sqlUserName3, sqlcon);
sqlUserName4 = "SELECT in_date FROM status where s_id='"+TextBox2.Text+"'";
SqlCommand sqlcmd4 = new SqlCommand(sqlUserName4, sqlcon);
string q3 = sqlcmd3.ExecuteNonQuery().ToString();
string q4 = sqlcmd4.ExecuteNonQuery().ToString();
DateTime dt1 = DateTime.Parse(q3);
DateTime dt2 = DateTime.Parse(q4);
TimeSpan result = dt1.Subtract(dt2);
string result1 = result.ToString();
TextBox8.Text = result1;
//Response.Redirect("login.aspx");
sqlcon.Close();
There are many things wrong with your code at the moment:
You shouldn't use string concatenation to build your query. Use parameterized SQL instead. This will avoid SQL injection attacks and conversion issues
You're using ExecuteNonQuery when you're trying to execute... a query.
You're converting the results into a string which is a bad idea even if it did return a date... instead, get the results in a form you can fetch as just a DateTime. Avoid string conversions wherever you can.
So you should:
Use parameters instead of dynamic SQL
Use ExecuteReader and get the first result from each reader
Use the GetDateTime method to get the DateTime from the results.
I would personally use the subtraction operator afterwards, too:
TimeSpan difference = end - start;
... but that's just a matter of preference, and not an actual mistake in your current code.
Your mistake is here:
string q3 = sqlcmd3.ExecuteNonQuery().ToString();
string q4 = sqlcmd4.ExecuteNonQuery().ToString();
DateTime dt1 = DateTime.Parse(q3);
DateTime dt2 = DateTime.Parse(q4);
ExecuteNonQuery does not return a date in a string representation. It returns the number of records affected by the query; hence, when you run DateTime.Parse(number) you get an error.
None of your queries are returning a date so it's unclear how you expect to get a date back from calling the SQL you have in your question...
Update
Do not use string concatenation to build your SQL Statements. You can use parameters to avoid exposing yourself to SQL Injection attacks. One example would be:
string sqlUserName3 = "SELECT out_date FROM status where s_id=#id";
SqlCommand sqlcmd3 = new SqlCommand(sqlUserName3, sqlcon);
sqlcmd3.Parameters.AddWithValue("#id",TextBox2.Text );
You use SqlCommand.ExecuteNonQuery() but you need SqlCommand.ExecuteScalar(). The first function returns nothing, it's supposed to be used for queries like insert or update. The second returns value of first cell of first row of query output.
You should use execute scalar or pass some out parameter to get value. This should get you some value in q3 and q4.
Now to avoid erros you should also use DateTime.ParseExact instead of simple Parse.
DateTime dt1 = DateTime.ParseExact(q3,"dd/mm/yyyy HH:mm",CultureInfo.InvariantCulture);
DateTime dt2 = DateTime.ParseExact(q4,"dd/mm/yyyy HH:mm",CultureInfo.InvariantCulture);

Categories

Resources