DateTime conversoin for DB querying - c#

I need to convert DateTime to string for purposes of DB querying.
I thought to do something like
_endTime.ToString(_isoDateTimeFormat.UniversalSortableDateTimePattern)
It works with MySQL, but SQL Server causes problems.
The final string looks like 2012-03-01 15:59:00Z seems z not supposed to be there.
Any suggestions?

You shouldn't be performing a text conversion at all.
You should be storing the data as a DATETIME (or whatever the corresponding type is in the database) and then you should be specifying the value in the query using a parameter, not including it in the SQL.
That way you don't need any string conversions in the first place.
Always pass values via parameters unless you have some really, really good reason why you absolutely have to include it in the SQL directly. Using parameters:
Protects you from SQL injection attacks
Removes conversion annoyances like this one
Keeps your code and data more logically separated

Related

How to pass list of guid as a parameter to a sql command

I need to filter a sql request by passing a list of id to , this is the command:
var command = "select Software.Name as SoftwareName,SoftwareType.Name as SoftwareType from AssetManagement.Asset as Software inner join AssetManagement.AssetType as SoftwareType on (SoftwareType.Id = Software.TypeId) where Software.Id in (#P)";
cmd.Parameters.AddWithValue("#P", authorizedSoftwaresId);
authorizedSoftwaresId is a list of string , containing data like :
"7D23968B-9005-47A9-9C37-0573629EECF9,F1982165-3F6D-4F35-A6AB-05FA116BA279"
with that it returns to me just one row, I tried adding quotes foreach value but i got "converstion from string caractere to uniqueidentifier failed " exception
This is a pretty common problem and the answer might depend on your database engine and whether you're using ADO.Net, Dapper, etc.
I'll give you some hints from my own experience with this problem on both MS Sql Server and PostgreSQL.
A lot of people think AddWithValue is a devil. You might consider Add instead.
The IN (#P) in your SQL statement might be the source of your problem. Try the Any option instead. See Difference between IN and ANY operators in SQL ; I've had success with this change in similar situations.
If all of your inputs are GUIDs, you might consider changing the type to a collection of GUIDs, although I don't think this is the fix, you have to try everything when you're stuck.
If you have to, you can parse the string version of your collection and add the ticks (') around each value. This choice has consequences, like it may prevent you from using a parameter (#P), and instead construct the final SQL statement you desire (i.e., manually construct the entire WHERE clause through string manipulations and lose the parameter.)
Good luck.

Store c# object in sql server database

I would like to store a c# object in SQL server. I thought about the following options:
Read object byte memory stream and save them into the database (but
not readable in sql)
Json, readable, easy to convert but what data type? (only a datatype for sql 2016)
XML, a bit less readable, easy to convert, there is an XML dataType
What's the best practice to store a C# object in a sql column and why?
I am using SQL 2014, so I think option 3 is the best?
Edit:
Note: it's not data to query, I just want to load a object which I have cached into a c# object in memory. And perform some logic on that in c#. It just takes a while to get the data from another database, therefore I save all my data in a custom object. Therefore I don't think I should use ORM
If it's just to throw in a database to read back at some point later by a key, then go with (2) and just use an nvarchar(max) field type.
If it's data to query, then you should probably design a schema to match and use an ORM.
If you are more positive towards option B, then you can store json-serialized string of any object[or datatype] in sql server as NVARCHAR(MAX) field.
And when you want to read it you can easily de-serialize that string in original format.
e.g.
Demo d1=new Demo();
//store this json into database.
string json= JsonConvert.SerializeObject(d);
// Now while reading fron db
Demo d2= JsonConvert.DeserializeObject<Demo>(json);
I'd go for JSON serialisation, it's just text, so when storing things like "user profile settings" or other types of structural data you're covered as you can read and write JSON in any language. Now SQL server has also understood this, like the XML support that was such a hype 8-10 years ago one can now store JSON with a good deal of TSQL support for those that need to update the data, like when you need to fix all updates for all user where...
anyway, have a look at the article. JSON in SQL Server 2016-2017
When going to and from JSON you should test your properties as some data types might not convert back and forward nice depending on things like regional specific settings like date and decimal values.

Different format for timestamp when using c# datareader

I'm reading a timestamp from a mysql table using an OdbcDataReader. When I look at the data in the table it is in the format 2013-09-12 11:11:09. But the reader seems to read it in the format 12/09/2013 11:11:09.
I then try to insert this into another mysql table but receive the error:
Incorrect datetime value: '12/09/2013 11:11:09' for column 'timestamp'
at row 1
How can I sort out this difference in formatting? Should I be referencing some Unix timestamp value somehow?
The data shouldn't be in the table in any text format. It's just a date and time.
You'll see the format when you convert the data to a string - which you should do as rarely as possible. In particular, when you're inserting the data into a different table, you shouldn't use a formatted value at all - you should use a DateTime in parameterized SQL.
Basically, unless you really need a string representation of the data, you should keep it in the "native" representation (DateTime in this case). Every time you have a conversion to or from text, that's an opportunity for failure. Dates and times are hard enough with time zones etc, without extraneous conversions getting involved.
How are you looking at the data "in the table"? I'm not familiar with the MySQL implementation, but with Oracle and Sql Server datetime values are stored in an unreadable binary format, and translated to a readable timestamp by the query tool. MySQL is likely doing something similar.
try to insert this into another mysql table
If you care about format when you're inserting the data, you're doing something really bad. That's a strong indication you're using a technique that will be vulnerable to sql injection attacks, rather than parameterized queries. If you use parameterized queries, you assign a C# datetime type to the query parameter value directly, and the ADO.Net object handles any formatting you need. At that point, anything you can successfully DateTime.Parse() or DateTime.TryParse() becomes a valid input for your query.

Use SQL to return a JSON string

This is a "best practice" question. We are having internal discussions on this topic and want to get input from a wider audience.
I need to store my data in a traditional MS SQL Server table with normal columns and rows. I sometimes need to return a DataTable to my web application, and other times I need to return a JSON string.
Currently, I return the table to the middle layer and parse it into a JSON string. This seems to work well for the most part, but does occasionally take a while on large datasets (parsing the data, not returning the table).
I am considering revising the stored procedures to selectively return a DataTable or a JSON string. I would simply add a #isJson bit parameter to the SP.
If the user wanted the string instead of the table the SP would execute a query like this:
DECLARE #result varchar(MAX)
SELECT #result = COALESCE(#results ',', '') + '{id:"' + colId + '",name:"' + colName + '"}'
FROM MyTable
SELECT #result
This produces something like the following:
{id:"1342",name:"row1"},{id:"3424",name:"row2"}
Of course, the user can also get the table by passing false to the #isJson parameter.
I want to be clear that the data storage isn't affected, nor are any of the existing views and other processes. This is a change to ONLY the results of some stored procedures.
My questions are:
Has anyone tried this in a large application? If so, what was the result?
What issues have you seen/would you expect with this approach?
Is there a better faster way to go from table to JSON in SQL Server other than modifying the stored procedure in this way or parsing the string in the middle tier?
I personally think the best place for this kind of string manipulation is in program code in a fully expressive language that has functions and can be compiled. Doing this in T-SQL is not good. Program code can have fast functions that do proper escaping.
Let's think about things a bit:
When you deploy new versions of the parts and pieces of your application, where is the best place for this functionality to be?
If you have to restore your database (and all its stored procedures) will that negatively affect anything? If you are deploying a new version of your web front end, will the JSON conversion being tied into the database cause problems?
How will you escape characters properly? Are you sending any dates through? What format will date strings be in and how will they get converted to actual Date objects on the other end (if that is needed)?
How will you unit test it (and with automated tests!) to prove it is working correctly? How will you regression test it?
SQL Server UDFs can be very slow. Are you content to use a slow function, or for speed hack into your SQL code things like Replace(Replace(Replace(Replace(Value, '\', '\\'), '"', '\"'), '''', '\'''), Char(13), '\n')? What about Unicode, \u and \x escaping? How about splitting '</script>' into '<' + '/script>'? (Maybe that doesn't apply, but maybe it does, depending on how you use your JSON.) Is your T-SQL procedure going to do all this, and be reusable for different recordsets, or will you rewrite it each time into each SP that you need to return JSON?
You may only have one SP that needs to return JSON. For now. Some day, you might have more. Then if you find a bug, you have to fix it in two places. Or five. Or more.
It may seem like you are making things more complicated by having the middle layer do the translation, but I promise you it is going to be better in the long run. What if your product scales out and starts going massively parallel—you can always throw more web servers at it cheaply, but you can't so easily fix database server resource saturation! So don't make the DB do more work than it should. It is a data access layer, not a presentation layer. Make it do the minimum amount of work possible. Write code for everything else. You will be glad you did.
Speed Tips for String Handling in a Web Application
Make sure your web string concatenation code doesn't suffer from Schlemiel the Painter's Algorithm. Either directly write to the output buffer as JSON is generated (Response.Write), or use a proper StringBuilder object, or write the parts of the JSON to an array and Join() it later. Don't do plain vanilla concatenation to a longer and longer string over and over.
Dereference objects as little as possible. I don't know your server-side language, but if it happens to be ASP Classic, don't use field names--either get a reference to each field in a variable or at the very least use integer field indexes. Dereferencing a field based on its name inside a loop is (much) worse performance.
Use pre-built libraries. Don't roll your own when you can use a tried and true library. Performance should be equal or better to your own and (most importantly) it will be tested and correct.
If you're going to spend the time doing this, make it abstract enough to handle converting any recordset, not just the one you have now.
Use compiled code. You can always get the fastest code when it is compiled, not interpreted. If you identify that the JSON-conversion routines are truly the bottleneck (and you MUST prove this for real, do not guess) then get the code into something that is compiled.
Reduce string lengths. This is not a big one, but if at all possible use one-letter json names instead of many-letter. For a giant recordset this will add up to savings on both ends.
Ensure it is GZipped. This is not so much a server-side improvement, but I couldn't mention JSON performance without being complete.
Passing Dates in JSON
What I recommend is to use a separate JSON schema (itself in JSON, defining the structure of the virtual recordset to follow). This schema can be sent as a header to the "recordset" to follow, or it can be already loaded in the page (included in the base javascript files) so it doesn't have to be sent each time. Then, in your JSON parse callback (or post-callback on the final resultant object) look in the schema for the current column and do conversions as necessary. You might consider using ISO format since in ECMAScript 5 strict mode there is supposed to be better date support and your code can be simplified without having to change the data format (and a simple object detect can let you use this code for any browser that supports it):
Date
Dates are now capable of both parsing and outputting ISO-formatted dates.
The Date constructor now attempts to parse the date as if it was ISO-formatted, first, then moves on to the other inputs that it accepts.
Additionally, date objects now have a new .toISOString() method that outputs the date in an ISO format.
var date = new Date("2009-05-21T16:06:05.000Z");
print( date.toISOString() );
// 2009-05-21T16:06:05.000Z
I wouldn't do that way you are doing (contatenating)
You can try creating a CLR SQL function that uses JSON.net and returns a varchar.
See here how to create SQL CLR Functions:
http://msdn.microsoft.com/en-us/library/w2kae45k(v=vs.80).aspx
Something like this (untested code)
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlString MyFunctionName(int id) {
// Put your code here (maybe find the object you want to serialize using the id passed?)
using (var cn = new SqlConnection("context connection=true") ) {
//get your data into an object
var myObject = new {Name = "My Name"};
return new SqlString(Newtonsoft.Json.JsonConvert.SerializeObject(myObject));
}
}

How can I trim string property datatypes from database char datatypes in Fluent NHibernate

I have a SQL database and a Oracle database with the same schema.
Therefore I want to use my model classes for the two databases and all I will do is change the database connection string in the Fluent NHibernate configuration.
I have some database char data types for columns but in my model classes I have set them as string however when they are returned from queries they have padded white space.
How do I return them trimmed without causing problems when I query the database using these colums as they will need to match the fixed length specification.
You can create an implementation of NHibernate.UserTypes.IUserType that will trim the whitespace when fetched from the database and re-pad it when going back to the database.
In your fluent mapping, you just add .CustomType<T> where T is your IUserType implementation.
This article is helpful for properly implementing IUserType. Don't get hung up on methods like Assemble, Disassemble, DeepCopy, Replace -- it doesn't look like you'll ever hit those, even. You're most concerned with NullSafeGet, in which you'll trim, and NullSafeSet in which you'll re-pad.
update
Upon further consideration, I'm not sure you'll actually need to re-pad the value when inserting to the database -- the db itself will enforce the fixed length of the column.
In response to the link you provided in your comment, I think that implementation pretty much gets you there, but I do think you might need to modify it a bit. For one thing, you may not want to trim both leading and trailing whitespace, as Trim() will do. For another, in your override of Equals, you'll want
value
to equal
value
The char data type in SQL databases is padded with whitespace.
If you can modify the database, you can create a view that trims the columns. But a trimmed value won't match the untrimmed value. (In a SQL query, that is.) TRIM() is a standard SQL function, but not all platforms support it. I suppose you might be able to cast it to VARCHAR(); I'm not sure I've ever tried that.
If I were in your shoes, I think I'd cache literally the value the database contains. (That is, I'd store it in a variable of some kind.) I might trim it for display to the user, but any interaction between my application code and the database would be done using the actual values in the database.

Categories

Resources