Azure SQL C# Backend Querying Float Caues "Internal Server Error" - c#

I have a pretty bazar one for you guys that I just can't figure out or even wrap my head around. I've created a few Azure databases in the past and I believe this is my second one using a .NET backend. I seem to have everything pulling/inserting correctly except for floating point variables.
Condensed class client side:
class MealItem
{
public string ID { get; set; }
public string Name { get; set; }
public float Price { get; set; }
}
Condensed class backend side:
public class MealItem : EntityData
{
public string Name { get; set; }
public float Price { get; set; }
}
And on the server side, the Price column (and other floats of the class) are set to the Data Type "float" with nulls allowed.
I am using sync tables, so the error is shown running this line:
await client.GetSyncTable<MealItem>().PullAsync("All", client.GetSyncTable<MealItem>().CreateQuery(),
CancellationToken.None);
I also tried this for the heck of it:
await client.GetTable<MealItem>().ToListAsync();
Everything works when I comment out the floating point variables on both the client and backend. I've spent a good amount of time on this one and can't seem to figure it out. Any ideas would be greatly appreciated! Thanks!

That error is related to a failed conversion from varchar to float data type that takes place when you are inserting data into the table. You wll have to validate "price" data before you can insert it to the table. If the TRY_CONVERT returns NULL you cannot insert that record because price value is not valid.

Foreshadowing While continuing to search for my problem, I looked at my database in SSMS and noticed that my "float" was taking 8 bytes.
The steps I took leading up to finding the issue were as follows. First, on the backend, I logged a Query().toString(); to get the SQL string being sent to the SQL database. Something like:
SELECT[Extent1].[Id] AS [Id],[Extent1].[Name] AS [Name],[Extent1].[ItemType] AS [ItemType], [Extent1].[Price] AS [Price],[Extent1].[Version] AS [Version],[Extent1].[CreatedAt] AS [CreatedAt],[Extent1].[UpdatedAt] AS [UpdatedAt],[Extent1].[Deleted] AS [Deleted]FROM [dbo].[MealItems] AS [Extent1]
I tried logging the result of this statement as an error but got nothing. Trying to poke around with the solution #albert Morillo posted, I tried
SELECT[Extent1].[Id] AS [Id],[Extent1].[Name] AS [Name],[Extent1].[ItemType] AS [ItemType], Try_convert(float,[Extent1].[Price]) AS [Price],[Extent1].[Version] AS [Version],[Extent1].[CreatedAt] AS [CreatedAt],[Extent1].[UpdatedAt] AS [UpdatedAt],[Extent1].[Deleted] AS [Deleted]FROM [dbo].[MealItems] AS [Extent1]
but still got no result. I finally had the bright of putting this statement in a try catch and logging the error there. It spat back the following:
"Error: The 'Price' property on 'MealItem' could not be set to a 'System.Double' value. You must set this property to a non-null value of type."
Not knowing what this meant, I looked for a double column type in SSMS. Not finding one, I decided to change my floats to doubles on the backend app. Magically, this seems to have done the trick.
I'm not sure if this is the proper solution, but it appears to work for me. Makes sense though since the SQL database is saving and 8 byte number and a C# double is 8 bytes.

Related

DateTime2 conversion randomly removes space between date and time

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.

SQL Timestamp to datetime on C#

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.

SQL Server or NHibernate truncating text

I have an MVC 3 project. In sql server I have a field called NewsContent which is a text field.
Here is the definition of the property in the Model:
[Display(Name = "Content")]
[DataType(DataType.MultilineText)]
[AllowHtml]
public virtual string NewsContent { set; get; }
When i save it to database it truncates. Well it is Text why is it truncating?
How can i fix it?
I can see in debugger that the object has all the text, when I look at database it is truncated.
Try this:
Map(x => x.NewsContent).CustomType("StringClob").CustomSqlType("nvarchar(max)")
In some NHibernate versions this truncating behavior was present due to the underlying ADO.NET having this behavior in certain circumstances. This was changed in NH 3.3 so that if the string is longer than allowed, NHibernate will throw an exception.
The above applies when using MS SQL Server as the database. If you are using this database, or still seeing this issue in this version of NHibernate, it should be regarded as bug that should be fixed. Please report it.

How to change EF decimal truncation behaviour

In entity framework, if you set the precision on a decimal column in your database to say 10,2, and update it in your EDMX, it will automatically truncate any decimals to 2 decimal places, correct?
I would prefer that it blow up in my face with an exception if I give it a number with a bunch of decimal places than have it silently truncate it, because it means I've not validated my data properly.
Is there a setting that I can set this? or am I going to have to attach to the savingchanges method and do some reflection?
To clarify with an example:
If I had a table called Invoice with a column called Amount. In my database this is a decimal(10,2) column, this is reflected in the EDMX, my entity says that this has a precision of 10 and a scale of 2.
Then in my code, lets say the user creates an invoice and they enter 10.23456 as the amount, I've forgotten to add some sort of clientside validation for this, so the amount gets sent to the server, my controller then saves an invoice with an amount of 10.23456. Entity framework will truncate this to 10.23 and be done with it.
What I want is this:
If I were to try and save an invoice with 10.23456 as the amount, EF sees that I have got a more precise value than my entity allows, and throws an exception. So this way my failure to validate inputs properly is discovered straight away.
You can«t make this configuration on the Entity Framework. But if you override your class and add some validation metadata on the properties, it will blow on you face with the validation error.
For example
[RegularExpression(#"^([\w-\.]+)#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$",
ErrorMessage = "ERROR MESSAGE")]
public string Email { get; set; }
OR
[StringLength(255, MinimumLength = 0, ErrorMessage = "ERROR MESSAGE")]
public string FriendlyName { get; set; }

Invalid cast from 'System.String' to 'System.TimeSpan' EF 4.1/MySql Connector/Net 6.4.4

For the life of me I cannot get this bug figured out - I have two time fields in mysql, properly mapping as Timestamp fields in ASP.net Entity Framework. I can assign and INSERT into the db no problem, however, whenever I try to load the data back out by simply querying the database I receive the following error message: Invalid cast from 'System.String' to 'System.TimeSpan'
using (hydraEntities db = new hydraEntities())
{
Employer = db.employers.Include("address").Where(em => em.EmployerId == EmployerId).First();
}
I cannot figure it out, i've upgraded the mysql connector to the latest release praying that would solve the bug - however that did not fix it. Any help would be GREATLY appreciated!
Try something like this.. TimeSpan is a deals with Length perhaps you meant TimeStamp..
what ever the case if you did mean TimeSpan.. can you double check and clarify..?
TimeSpan would work.. here is a something you could use.. problem is you will need to figure out the milliseconds of what's in the timespan field to replace your milliseconds with what I have pasted in this code example
DateTime dt = new DateTime().Add( TimeSpan.FromMilliseconds( 1304686771794 ) )
Ok so this post is about how people have approached storing the time of day.
C# DateTime: What "date" to use when i'm using just the "time"?
its not really something that C# understands as such so anything is a bit of a work around. If you really want a timespan you would probably be best to store that as an int in the database for the number of ticks in the timespan, then convert it in your model.
Another option would just to be to store the hours/minutes components in a data structure of your own.
eg
public class TimeOfDay
{
public int Hours{get;set;}
public int Minutes{get;set;}
//possibly even
public TimeSpan TimeSpan
{
get
{
return new TimeSpan(new DateTime(2000,1,1,Hours,Minutes,0).Ticks -new DateTime(2000,1,1).Ticks);
}
}
}

Categories

Resources