SqlDateTime overflow when inserting value with DateTime.Now - c#

Lately I have quite odd error while trying to do db.SubmitChanges():
SqlDateTime overflow. Must be between 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM.
The point is, I only use DateTime.Now to set property in my object, and after calling Response.Write(DateTime.Now.ToString()); it shows 17-04-2013 18:03:13 as it should be.
It was not happening earlier, and now the function always breaks. I'm completely clueless - date on my SQL server seems to be ok.
What may cause it?
Edit
I don't think it would help (it just too simple to have any errors IMO), but there's my function:
public bool ReportLogIn(int UserID, string IP, int Succeed ... ) {
A_UserLoginHistory Report = new A_UserLoginHistory();
Report.IP = IP;
Report.UserID = UserID;
Report.Status = Succeed;
Report.Date = DateTime.Now; //the only DateTime field
...
try {
db.A_UserLoginRegistry.InsertOnSubmit(Report);
db.SubmitChanges();
return true;
} catch (Exception e) {
ErrorLog.AddError(e.ToString());
return false;
}
}

actually the problem is SQL DateTime =/= C# Datetime
you need to change 2 things
Database change the field type from DateTime to DateTime2
Query you need to be explicit
SqlCommand cmd = new SqlCommand("insertsomeDate", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#newDate", SqlDbType.DateTime2).Value = yourDate; //<- as example
you can find futher informations here,here and here

Most likely thing is that you have forgotten to initialise a date field - are you sure you've set them all and haven't added a new one? I usually get this when I add a new date field to the DBML as it tries to insert 01/01/0001 00:00:00
If that doesn't help, set a New StringWriter on DB.Log before you do DB.SubmitChanges and examine DB.Log.ToString afterwards (can do in the debugger). This should show you the query and all parameters (at the bottom) so you can see match up what parameter is causing the problem.
Another thing that helps with this kind of problem is using DB.GetChangeSet() to check what records and being inserted/updated before the SubmitChanges call (can't imagine a delete could cause this)

Related

DateTimePicker.MinDate Issue

I want to set the minimum and maximum date on a DateTimePicker in VS2015. I want to set the minimum date to a value from my database, and the maximum date to DateTime.Now. I have the following code:
SQLiteCommand cmdForShopRegDate = new SQLiteCommand(#"select Date from [ShopRegistration]", con);
SQLiteDataAdapter AdapterShopRegDate = new SQLiteDataAdapter(cmdForShopRegDate);
DataTable TableShopRegDate = new DataTable();
AdapterShopRegDate.Fill(TableShopRegDate);
this.dateTimePickerStartReport.MaxDate = System.DateTime.Now.Date;
this.dateTimePickerStartReport.MinDate = Convert.ToDateTime(TableShopRegDate.Rows[0][0].ToString());
I am getting the following error:
Value of '18-Jul-28 12:00:00 AM' is not valid for 'MinDate'. 'MinDate' must be less than MaxDate.
Your question isn't very detailed and seems like you are asking others to perform your work for you. Even though this may be a learning experience, please read how to ask a thorough question.
The issue you are having is related to the formatting of your data. You're parsing a value of 18-Jul-28. The issue is that this parses as 7/18/2028 which is definitely greater than 8/2/2018. To fix this, you'll need to parse with this format:
yy-MMM-dd
Other than that, your code can also be simplified (unless you absolutely need your DataTable). SqlLiteCommand.ExecuteScalar returns the first column of the first row in your result set and ignores all other data.
using (SqlLiteConnection conn = new SqlLiteConnection("put your connection string here")) {
using (SqlLiteCommand cmd = new SqlLiteCommand("select Date from [ShopRegistration]", conn) {
conn.Open();
dateTimePicker.MinDate = DateTime.ParseExact((string)cmd.ExecuteScalar(),
"yy-MMM-dd",
CultureInfo.InvariantCulture).Date;
}
}
dateTimePicker.MaxDate = DateTime.Now.Date;
You'll need to add using System.Globalization; to your usings for access to CultureInfo.
References:
DateTime.ParseExact
CultureInfo.InvariantCulture
Custom Date Formatting

Comparing two datetimes to check for a clash but seems to be confusing MM/DD with DD/MM C# ASP.NET

I am trying to check my database for a clash, I am reading up using a reader and calling the value down. My value is 10/12/2018 15:00:00 So I have stored this as #moduleStartTime
My next query checks the database using the above datetime and if it is between any other dates entered.
The issue I am encountering is that there are no clashes, so this shouldn't flag up that there are. I have found that the clash it is returning has a datetime of 12/10/2018 15:00:00
It appears as though somewhere in the search, it is reversing DD/MM
Here is my code
//Reading to get all modules student is enrolled on
string checkclash = "SELECT * FROM cModuleTimes INNER JOIN cStudentModule ON cModuleTimes.ModuleID = cStudentModule.ModuleID WHERE cStudentModule.StudentID=#studentid AND #date BETWEEN[StartTime] AND[EndTime] AND ModTimeID <> #modtimeid";
SqlCommand myCommandclash = new SqlCommand(checkclash, myConnectionclash);
myCommandclash.Parameters.AddWithValue("#date", moduleStartTime);
myCommandclash.Parameters.AddWithValue("#courseid", courseid);
myCommandclash.Parameters.AddWithValue("#studentid", user);
myCommandclash.Parameters.AddWithValue("#modtimeid", moduletocompareid);
//create a sqldatareader object that asks for dats from a table
SqlDataReader rdrreadclash = myCommandclash.ExecuteReader();
if (rdrreadclash.HasRows)
{
while (rdrreadclash.Read())
{
string getname = rdrreadclash["ModTimeID"].ToString();
string gettime = rdrreadclash["StartTime"].ToString();
Warning.Text = "There appears to be a clash with this event..<br><br> <br> <b>Would you like to continue?</b> <br><br>";
}
ViewClash.Visible = true;
YesContinue.Visible = true;
FinishMod.Visible = false;
}
myConnectionclash.Close();
I have tried a couple of conversions but am receiving an issue with string not recognised as a DateTime.
If anyone has any answers on how I would prevent this clash from appearing, I would be very grateful.
Thank you.
moduleDateTime is currently a string, you need to parse it in to a DateTime object where the parsing operation has the proper MM/DD order you want.
DateTime dateAsDateTime = DateTime.ParseExact(moduleStartTime, "dd/MM/yyyy HH:mm:ss", null);
myCommandclash.Parameters.AddWithValue("#date", dateAsDateTime);
You then must format the returned date time back to a string in the format you want.
string gettime = ((DateTime)rdrreadclash["StartTime"]).ToString("dd/MM/yyyy HH:mm:ss ");

Utc Date saving as Local date in Sqlite

I have an Sql database which contains a date field.
I use Dapper to update the database as follows:
const string sql = "UPDATE AdminDb.Users " +
"SET IsLoggedOn = 1, LastLoggedOn = #LastLoggedOn " +
"WHERE Username = #username";
var date = DateTime.UtcNow;
DatabaseConnectionBase.DatabaseConnection.Execute(sql, new { username, LastLoggedOn = date });
I am finding to my great annoyance when breaking before the actual update, the date variable reads 30/3/2015 9:32:54 however when I run the update the database saves the date as 30/3/2015 10:32:54
As the UK yesterday changed from GMT to BST (UTC +1) I am sure that the database seems to be trying to compensate for this as this issue never came up before.
I thought I had averted this sort of issue by using the DateTime.UtcNow property to save my date.
This is causing serious issues when validating users.
I am sure it is not my code as the date is correct going into the Dapper Execute method.
I can't see why Dapper would try to compensate as most developers would be screaming at such functionality
Which leads me to the conclusion that it must be something in Sqlite that is causing this issue. Perhaps there is a pragma I need to run?
As per a suggestion from another site I tried formatting the date as follows:
var date = DateTime.UtcNow.ToString("o");
The intention being to force the date into ISO-8601 format but I had no luck with that.
Has anyone got any ideas?
Thomas Levesque has the solution here:
// You just need to specify DateTimeKind=Utc in your connection string:
string connectionString = #"Data Source=D:\tmp\testSQLiteDate.db;DateTimeKind=Utc";
This happened to me too.
What I did was serialize the datetime to a string myself before adding it as a parameter.
internal const string DateTimeFormat = "yyyy-MM-dd HH:mm:ss";
cmd.Parameters.Add("#Threshold", DbType.DateTime).Value = threshold.ToString(DateTimeFormat);
If you do the same thing with pure ADO.NET, does the same thing happen? I wonder if this is a database thing or a provider thing, rather than a library thing. Dapper has to ToLocalTime() or ToUniversalTime() calls - it passes the time through unaltered. On SQL Server, the following works fine in a BST setting:
public void SO29343103_UtcDates()
{
const string sql = "select #date";
var date = DateTime.UtcNow;
var returned = connection.Query<DateTime>(sql, new { date }).Single();
var delta = returned - date;
Assert.IsTrue(delta.TotalMilliseconds >= -1 && delta.TotalMilliseconds <= 1);
}

MS Access stores the incorrect DateTime.MinValue?

I have a problem when storing DateTime.MinValue into a field (as Date/Time type) in MS Access. Printing this out prior to storing in database, I get "1/1/0001 12:00:00 AM", which is expected. However after retrieving the same value out of the database I get "1/1/2001 12:00:00 AM" (note the year 2001 instead of year 1).
This is obviously incorrect! Anyone have any ideas?
Note, that I am using DateTime.MinValue as someone suggested as invalid date/time, because DateTime cannot be null value.
The code to write to database is:
public static bool StartNow(string profileID, string startNotes)
{
DateTime now = DateTime.Now;
OleDbCommand cmd = new OleDbCommand("SELECT * FROM shifts WHERE profile_id=#profile_id AND closed=false;");
cmd.Parameters.AddWithValue("#profile_id", profileID);
// A new shift should NEVER be started with another open shift.
OleDbDataReader reader = Database.Read(cmd);
if (reader.HasRows)
return false;
cmd = new OleDbCommand("INSERT INTO shifts(profile_id, start, stop, start_log, stop_log, start_notes, stop_notes, closed) VALUES(#profile_id, #start, #stop, #start_log, #stop_log, #start_notes, #stop_notes, #closed);");
cmd.Parameters.AddWithValue("#profile_id", profileID);
cmd.Parameters.AddWithValue("#start", RoundUp(now, 30).ToString());
cmd.Parameters.AddWithValue("#stop", DateTime.MinValue);
cmd.Parameters.AddWithValue("#start_log", now.ToString());
cmd.Parameters.AddWithValue("#stop_log", DateTime.MinValue);
cmd.Parameters.AddWithValue("#start_notes", startNotes);
cmd.Parameters.AddWithValue("#stop_notes", "");
cmd.Parameters.AddWithValue("#closed", false);
// TODO: need to set default values for stop, stop_log and stop_notes
return Database.Write(cmd) == 1 ? true : false;
}
This is the code to read back in the date and time:
public static List<ShiftView> TodaysShifts()
{
List<ShiftView> shifts = new List<ShiftView>();
// INFO: Not intended to retrieve a lot of records as there is no caching....
OleDbCommand cmd = new OleDbCommand("SELECT profiles.profile_id, profiles.full_name, shifts.start, shifts.stop, shifts.start_log, shifts.stop_log, shifts.start_notes, shifts.stop_notes FROM shifts, profiles WHERE (shifts.start>=#today) AND (shifts.profile_id=profiles.profile_id);");
cmd.Parameters.AddWithValue("#today", DateTime.Today);
OleDbDataReader reader = Database.Read(cmd);
while(reader.Read())
{
shifts.Add(new ShiftView(
reader.GetString(reader.GetOrdinal("profile_id")),
reader.GetString(reader.GetOrdinal("full_name")),
reader.GetDateTime(reader.GetOrdinal("start")),
reader.GetDateTime(reader.GetOrdinal("stop")),
reader.GetDateTime(reader.GetOrdinal("start_log")),
reader.GetDateTime(reader.GetOrdinal("stop_log")),
reader.GetString(reader.GetOrdinal("start_notes")),
reader.GetString(reader.GetOrdinal("stop_notes"))
));
}
return shifts;
}
In Microsoft Access "Valid date values range from -657,434 (January 1, 100 A.D.) to 2,958,465 (December 31, 9999 A.D.). Valid time values range from .0 to .9999, or 23:59:59." (ref: here.) So, you cannot store "1/1/0001 12:00:00 AM" in an Access Date/Time field.
As suggested by Jon Skeet :-
Basically, don't use DateTime.MinValue to represent a missing value.
You can't use DateTime.MinValue in a SQL Server DateTime field, as SQL
Server has a minimum value of the start of 1753.
Instead, make your property a Nullable (aka
DateTime?), and set it to null when you don't have a value. Also make
sure your database field is nullable. Then you just need to make sure
that that null ends up as a NULL value in the database. Exactly how
you do that will depend on your data access.
and you can give a try to use SqlDateTime.MinValue instead of DateTime.MinVaue

Date read from Database in wrong format?

I'm using DateTime in my C# winforms tool, and I'm storing dates into an SQL database using this line:
iDisc.acquirementDate.ToString("yyyy-MM-dd")
The SQL database field is of DATE type, and when this date is stored, its stored correctly, such as this: 2013-03-14
When I want to the value, I use this line:
DateTime acquirementDate = DateTime.ParseExact(iDiscRow[TableNames.Discs.acquirementDate].ToString(), "yyyy-MM-dd", CultureInfo.InvariantCulture);
However, a FormatException occurs at the above line, because the string being parsed is not a valid DateTime complaint string.
The value this is being parsed is the this: 3/14/2013 12:00:00 AM
What I don't understand is, why is the value read as 3/14/2013 12:00:00 AM, when in the database its stored as 2013-03-14 ?
I'm using SqlDataReader to retrieve the data from database. Can post that code here, but I don't think its needed as its very basic.
It seems that your iDiscRow[TableNames.Discs.acquirementDate] is DateTime already. In that case you just have to cast it.
DateTime acquirementDate = (DateTime)iDiscRow[TableNames.Discs.acquirementDate];
And reason why you're getting 3/14/2013 12:00:00 AM is that DateTime.ToString() uses current thread culture to trasnform DateTime to string. Since it's WinForm app, I guess this is your Windows system format for DateTime.
The row is retrieved as an object. The ToString() method is formatting it. You need to pass the format you want to use to the ToString() method.
This answer is only relevent if it's possible for the database value to be null. That is frequently my own situation, so I wrote this function in a helper class in a class library.
public DateTime? SetDateTimeValue(DataTable dataTableIn
, int rowNumber, string fieldName)
{
DateTime? returnValue = new DateTime?();
DateTime tempValue = new DateTime();
try
{
string fieldValueAsString = dataTableIn.Rows[rowNumber][fieldName].ToString();
result = DateTime.TryParse(fieldValueAsString, out tempValue);
if (result)
returnValue = tempValue;
}
catch
{
returnValue = null;
}
return returnValue;
}
Here is a sample call
DataTable data = dataAccess.GetEmergencyVisitDataFromClinicalApplicationSupport(VisitID);
if (data.Rows.Count == 1)
{
ValueSetter setterOfValues = new ValueSetter();
skip a bunch of lines.
AdmitDecisionDateTime =
setterOfValues.SetDateTimeValue(data, 0, "admit_decision_datetime");

Categories

Resources