I have a small console application which is to import a CSV file into a database. It is in .NET CORE 3.1. The CSV file gets imported without any issues. The issue arises with trying to save the data to the table. The error being received is "String or binary data would be truncated. The statement has been terminated." This is received during the context.SaveChanges() call. To determine exactly what the error is, loaded up Profiler to see the offending statement. The offending piece of code was related to a field that holds a date and time. To start from the beginning and lead up to the issue.
The imported data is in a column and is represented as follows:
"20200404121655500"
"20200404121755500"
The import model property is defined as follows:
public string Date_And_Time { get; set; }
The data model property is defined as follows:
[Column(TypeName = "DATETIME2(7)")]
public DateTime? Date_And_Time { get; set; }
The conversion used to get the imported string to the data model field is as follows:
if (DateTime.TryParseExact(Date_And_Time.Trim()
.PadRight(21, '0')
.Substring(0, 21), "yyyyMMddHHmmssFFFFFFF", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime newDateTime))
{ model.Date_And_Time = newDateTime; }
else { model.Date_And_Time = null; }
While debugging when the 2 different dates are processed then are set in the model.Date_And_Time as expected. The object expands producing all the correct information (year, day, hour, etc.). Prior to executing SaveChanges, inspecting the objects shows they both have correct DateTime objects. However upon executing that command throws the above SQL exception. When inspecting the merge command created by EF the dates are differently formatted. They are as follows:
'2020-04-0412:16:55.5000000' and '2020-04-04 12:17:55.5000000'
The first does not have a space between the date and time where as the second has a space. The first is what is causing the exception. When doing the SaveChanges there are on average 20 records being saved and some have the space and some do not there is no pattern that I can find. I have tried using the exact same date time and that also has some with and some without space.
After some trial and errors I switched from DateTime to DateTimeOffset. This was done on the property of the data model propriety, the type attribute of the same property and the TryParseException. No other changes and it ran with no exceptions. Needed to do another migration due to the change in attribute causing the table field tire change.
The only 3rd party package used was to import the CSV for and that went successfully.
The parametrized merge statement was seen in the profiler sorry I didn't City it better finding the answer.
I have no idea why the model with a C# data type of DateTime would produce a string although the parameter itself was designated as DateTime2 the value being passed in was in string format.
I don't understand what the difference is between the 2 data types and how they are handled that would cause this issue. I appreciate the comments and attempting to help.
Related
I'm completely fresh to Blazor and have just dived into a project.
I'm using ORM to pull up data from a database. For some reason when I return the data, it is being shown as 1/1/0001 12:00:00Am
This is how I grab the data from DB
string sql = "Select top Value1, Value2, Value_DateTime from DBO.T_1";
return _db.LoadData<Model1, dynamic>(sql, new { });
And this is how I try to populate a table with a value, in .Razor page
<td>#Value.Value_DateTime</td>
All other data appears correctly. When I run the query in SSMS, it shoes correct dates.
EDIT:
Task<List<T>> LoadData<T, U>(string sql, U parameters);
The issue might be incompatibility between SQL DateTime datatype and C# System.DateTime struct. There is an alternative version: System.Data.SqlTypes.SqlDateTime struct - switching to that struct in your Model should™ fix your problem.
Here's the docs link: https://learn.microsoft.com/en-us/dotnet/api/system.data.sqltypes.sqldatetime?view=dotnet-plat-ext-3.1
Relevant excerpt:
...The SqlDateTime structure has a different underlying data structure from its corresponding .NET Framework type, DateTime...
Blazor C# date shows as 1/1/0001 12:00:00Am
You are showing a DateTime that has not been initialized. Somewhere in your code you are simply not moving the data from the database into the field that you then show out. Sadly, your code is so non-standard I will not debug it - especially because of unneeded use of dynamics - but somewhere there you make a mistake.
I have the following column on my SQL table:
RECORDTIMESTAMP
0x000000000005B2A4
0x000000000005B2A5
0x000000000005B2A6
And I need to return this values on my C# program. This atributte is declared like this:
public DateTime? RecordTimeStamp{ get; set; }
And my method to get is this one:
RecordTimeStamp = DateTime.Parse(row["RecordTimeStamp"].ToString()),
The error message is the following:
"The string was not recognized as a valid DateTime. There is an unknown word starting at index 0.",
I also tried to declare the atribbute as string but it didn't worked also.
Any Ideas on this?
A common misconeption here: Timestamp is not actual a time.
It was a miss-naming. That is why it was renamed to ROWVERSION half a dozen versions ago. Timestamp was only still used as Alias, with a clear "deprecated" marker. From
https://learn.microsoft.com/en-us/sql/t-sql/data-types/rowversion-transact-sql:
timestamp is the synonym for the rowversion data type and is subject to the behavior of data type synonyms. In DDL statements, use rowversion instead of timestamp wherever possible. For more information, see Data Type Synonyms (Transact-SQL).
The Transact-SQL timestamp data type is different from the timestamp data type defined in the ISO standard.
Note
The timestamp syntax is deprecated. This feature will be removed in a future version of Microsoft SQL Server. Avoid using this feature in new development work, and plan to modify applications that currently use this feature.
That looks like a rowversion column (which has historically been called a "timestamp" column, despite it not being a stamp of the time). A rowversion is not a time - it is just an opaque monotonically incrementing integer that means nothing other than it lets you spot that a change has happened. Timestamps are often used for optimistic concurrency checking, but have no actual meaning. Depending on the size, a long, or a byte[] or a string might be fine for storage.
Just started getting this error today. Only one user is having this error.
Year, Month, and Day parameters describe an un-representable DateTime.
I can recreate the error locally, but stepping through the debugger the error is thrown on a line that has nothing to do with dates or times. In the code a custom DAL queries an Oracle database and returns an OdbcDataReader, which is then iterated to populate a domain object. The database will have one or more records for each user. The exception is thrown when reading a char field into a string property. The code looks like this:
while (reader.Read())
{
var program = new MyDomainObject();
program.Code = reader["code"].ToString();
program.Year = reader["year"].ToString();
program.Title = reader["title"].ToString();
program.Status = reader["status"].ToString(); <-- thrown on this line
... etc, then append the domain object to an IList and repeat
}
The status field is a non-nullable char(1) field in the database. Example status codes are 'A', 'B', 'Q', 'W', etc. I extracted the query and ran it directly against the database for that user and it works perfectly, so the issue is in the above code somehow. There are three date fields in that table that are used in this code, but the error is not thrown on any of those lines, and besides there is a null check for the one field that can be null. So I just don't see why this is happening here.
9,000 users since we launched the app a few days ago and this is the only error of this kind so far. Any ideas why this would be thrown here? Thanks.
This line
program.Status = reader["status"].ToString();
is never, ever going to throw that exception. There's probably some mismatch between the line number reported in the exception and the source code you're looking at. Maybe the source code you're reading is different from what was deployed.
I'd look for a nearby line that does construct a date, and if not, one that reads a date. Somehow some data has gotten into your table that doesn't represent a valid date. Perhaps a user has some different culture setting and somehow their input made its way into a table. Like 30/4/2016 instead of 4/30/2016, or something along those lines.
The exception is good. When you find the cause I bet that it's going to accurately describe what's happening. It's just the indication of which line it's on that's misleading you.
I came across this. Does it help? It looks like this exact error has come up before when reading dates from an Oracle database. Oracle might allow storing an empty date in a manner which is unreadable to .NET.
I have an app which worked fine with Sql Server. I have a DevExpress grid which shows just a record in carousel mode (not that this matters, I hope).
Now, I have changed the code to be database-agnostic and I'm testing MySql. When the user modified the record and accepted the changes, I was getting the following error:
Concurrency violation: the UpdateCommand affected 0 of the expected 1
records
After some research, I've come to the conclussion that the problem lies in DATETIME fields. I am using "Allow Zero Datetime=False; Convert Zero Datetime=True;" in my MySql connection string so I can convert default DATETIME values to .Net DateTime objects. The autogenerated UpdateCommand includes every field in the where clause, and I guess the comparison fails when the MySql DATETIMEs are set to the default value, as removing DATETIME fields the problem went away.
I have a Primary Key column, and the user isn't allowed to modify it, so what's the right way to issue a custom UpdateCommand so that there's only one field in the WHERE clause?
My current code for accepting changes:
Dim builder As DbCommandBuilder = m_Conn.CreateCommandBuilder(m_Adapter)
m_Adapter.Update(m_DataTable)
CreateCommandBuilder is an extension method on IDbConnection to create the correct an object with a correct implementatin of the DbCommandBuilder interface.
Your DBCommandBuilder should have a ConflictOption Property that needs to be set.
Presumably you want to set it to ConflictOption.OverwriteChanges.
I'm not sure if it works when you initialize the Adapter commands via the CommandBuilder Constructor but a
var builder = new MySqlCommandBuilder();
builder.ConflictOption = ConflictOption.OverwriteChanges;
builder.DataAdapter = m_Adapter;
should do.
Instead of using "Allow Zero Datetime=False; Convert Zero Datetime=True;" in your connection string (which FYI I'm not familiar with), I'd recommend using DateTime.Parse(value). You'll probably want to write a function so that you can easily handle nulls as well.
private DateTime getDateTimeField(string dbValue)
{
if (dbValue == null)
{
return new DateTime();
}
else {
return DateTime.Parse(dbValue);
}
}
I've been through a tough day facing this problem. In ent object, I have DiinputTanggal property as Date. In database, I have DiinputTanggal column as DateTime. When I try to insert the ent object into the database, I got the following error shown in the screenshot below. But when I debug, the property DiinputTanggal in ent object seems perfectly fine and nicely formatted. I have no idea where is my mistake.
Looking at your screenshot, it is probably the TaggalAktif property which is causing the overflow. .Net DateTimes default to DateTime.MinValue which cannot be represented in SQL DateTime.
You have several options
Initialize the DateTime to a value supported by Sql DateTime (in the range indicated by the error)
Change the DateTime to be nullable in both the class and database, (and ensure the property is initialized to null).
Use another Sql DataType to store the data e.g. DateTime2 or just Date if time isn't needed.