SQL: .. contains an unresolved reference to an object - c#

Full message
Parameter: [DbName].[SpName].#timeout contains an unresolved reference to an object. Either the object does not exist or the reference is ambiguous because it could refer to any of the following objects: [dbo].[TIME]
I know, there is couple of Question already exists with this message. But this one in my example happens especially because of TIME Sql type.
I Have StoredProcedure ( in Visual Studio Sql Database project ) which is looks like this.
CREATE PROCEDURE [dbo].[my_sp]
#name VARCHAR(255),
#timeout TIME
AS
...
I have no any table with name TIME. When I change the type TIME with other, it stars work correctly, other way it shows this message in TIME type and compile time error.
TIME I trying to use as a SQL alternative for C#'s TimeSpan.

You can't use time with SQL Server 2005, since it didn't exist until SQL Server 2008.
Instead, consider storing a numeric representation of the time interval (which is, ultimately, what time is anyway - just: you'd be doing it explicitly rather than automatically). Typical examples would be to store, as an int, the number of seconds or milliseconds represented by your time interval.
Conveniently, TimeSpan has a TotalSeconds and TotalMilliseconds property that maps to this (just: convert it to an integer), and has FromSeconds(...) and FromMilliseconds(...) methods for going the other direction.
From comments, it sounds like you also need features to combine (add) times to dates; this is also easy:
DATEADD(second, {interval as seconds}, {some datetime})
or
DATEADD(millisecond, {interval as milliseconds}, {some datetime})

Related

sp_executesql Causes Undesired Implicit Conversion

I've been suffering from this for a while now. In SQL Server Profiler, I confirmed that using SqlDataAdapter.Fill produces a sp_executesql command. Sometimes, the query takes too long to execute, the cause used to be one of the following two cases:
All of my text database fields are varchar. We know that sp_executesql only accepts unicode types (nvarchar, nchar). Specifying SqlDbType.Varchar for the parameter type in C# sometimes causes a big performance problem (for certain queries) because of the fact that an implicit conversion takes place in order to convert the varchar parameter to the nvarchar needed for sp_executesql. Aparently, that conversion was taking place on every row scan.
So I specified SqlDbType.NVarChar instead and the problem is solved temporarily. One day, I ended up having the same performance problem (for a different query) for the same cause but in another way. An implicit conversion was taking place to convert all the varchar values in the specified database column to nvarchar. Reverting the type to SqlDbType.VarChar fixed the problem for that case.
I know the problem is not due to Parameter Sniffing because I tried using sp_updatestats to refresh the cached plans and using OPTION(RECOMPILE) to make sure a new plan gets generated. But that did not solve the problem.
I cannot wrap my head around this and I wish to avoid using sp_executesql altogether if possible. Any idea how to avoid the undesired implicit conversions?
EDIT: It's worth noting that the queries that are generated are dynamic (coming from a query builder feature). Also, it's worth noting that the problem only showed when a "contain" operand (in sql: like %%) was used.
EDIT: This good article emphasizes the same problem. However, he author sadly declares that there is no solution.. yet, hopefully.

MS SQL how to record negative time

I have a column in the MS SQL database with type “TIME”. I need to record a negative value in it. It isn't a range between two certain times or dates. It’s an abstract value of time that is used in calculations. In the entity framework it is treated as a TimeSpan, which MetaData.tt does automatically with all TIME defined columns in the database.
For example, I might have an arbitrary calendar with events at 5AM and 8PM on Monday, one at 4PM on Tuesday, and one at 3AM on the Sunday after that. I could add the value to these times and get a time either before (in case of negative time), or after (in case of positive time) the beginning of the event.
When I try to write down a negative value, the database refuses it.
The recording of entity to database goes by direct bind of post attributes in the controller, so if it needs to be translated into ticks, is it reliable to do so in Javascript? How would I go about the input textbox for it? It looks like I cannot separate the value from the content in a text box. And if I have to turn it into an INT, I cannot use #EditorFor on it anymore, creating another point of fault where code becomes less flexible.
It almost feels like I should create new columns to denote the negativity of these values and use a dropdown list with hidden inputs instead of a textbox.
EDIT:
Why avoid non-time types:
Consider this code:
var typeName = _code.Escape(edmType.MetadataProperties.Where(…).FirstOrDefault());
If the EDM property has the type int, the generated code will be the type int.
The EDM property comes from the database itself, so if it is not a type that translates directly into a time, then there will need to be a new method (somewhere in a helper, perhaps), which translates this into a time. This new method will have to be maintained (by other people on the team), which means a weak point, because if someone changes the column name, now the code will not just get properly generated again.
Errors may also not be available through the error log, since most properties also tend to be referenced in javascript at some point (which is often also generated, and now can't be for this column because it is a special case). I'm also talking about some 20 columns suffering from this, so this has a very good potential to quickly turn into a deeply tangled ball of spaghetti.
It really seems like you are trying to store a duration, not a time. TIME is used for storing a point in time, not an amount of time. I would choose some subdivision of time (second, millisecond, etc), and store that as an int (or bigint if necessary). Then in SQL Server you could use DATEADD(SECOND,#storedValue,#dateToChange) to calculate the true time or DateTime.Add.Milliseconds(storedValue) or DateTime.Add.Seconds(storedValue), so on, in C# when trying to calculate the time you want.
Let me know if I'm missing something.
In these cases I think I would store both Begin and End times and have another Computed Column to store the difference (with INT datatype) using DATEDIFF:
CREATE TABLE dbo.MyTable
(
Time1 time
Time2 time
timedifference AS DATEDIFF(Second, Time1,Time2)
);
Then you can convert the Seconds into a time of day like this:
SELECT CONVERT(varchar, DATEADD(ms, timedifference * 1000, 0), 114)
Here is a working sample of what you will get:
SELECT CONVERT(varchar, DATEADD(ms, DATEDIFF(Second, CAST('12:24:18.3500000' as time),CAST('11:24:18.3500000' as time)) * 1000, 0), 114)
SELECT CONVERT(varchar, DATEADD(ms, DATEDIFF(Second, CAST('11:24:18.3500000' as time),CAST('12:24:18.3500000' as time)) * 1000, 0), 114)
Database type time does not support negative values. The acceptable range is 00:00:00.0000000 through 23:59:59.9999999
https://msdn.microsoft.com/en-us/library/bb677243.aspx

How to save and show elapsed time correctly in datagridview?

I want to save elapsed time in a form into sql table
timer started at form load event and when I click the save button try to save it with
cmd.Parameters.AddWithValue("#duration", textBox3.Text);
in sql table and duration column data saved like this: 00:22
and this absolutely correct for my job
but in datagridview's duration column time showed like this:03/16/2015 12:22pm
Why data in datagridview converted to a full date data instead of original elapsed time?
Well, you didn't give us enough information about your problem but I try my best..
first time it was a float data type but i changed it to nvarchar(255)
for better performance in saving data from c# program
Based on your data (which is 00:22) neither float not nvarchar are seem the right type in your database.
If this is a time interval, time type can be the right type since it is a time of a day. But this time type can't hold bigger than 24:00 values. You will get an error when you try to insert it a bigger value.
If this data can be more bigger than 24:00, I would suggest to parse it to TimeSpan first and save it's Ticks property to bigint typed column in your database.
Looks like your program takes your 00:22 and parse it to DateTime in somehow like DateTime.Parse("00:22"), that's why it generates a today's date with parsed time of day as a DateTime in your datagridview.
By the way, don't use AddWithValue method as a best practice. It may unexpected results sometimes. Use .Add() method overloads to specify your SqlDbType and it's size.
Further reading:
Bad habits to kick : choosing the wrong data type
Can we stop using AddWithValue() already?

.NET DataRowComparer DateTime Comparison To T-SQL DateTime

I have learned that SQL Server stores DateTime differently than the .NET Framework. This is very unfortunate in the following circumstance: Suppose I have a DataRow filled from my object properties - some of which are DateTime - and a second DataRow filled from data for that object as persisted in SQL Server:
DataRow drFromObj = new DataRow(itemArrayOfObjProps);
DataRow drFromSQL = // blah select from SQL Server
Using the DataRowComparer on these two DataRows will give an unexpected result:
// This gives false about 100% of the time because SQL Server truncated the more precise
// DateTime to the less precise SQL Server DateTime
DataRowComparer.Default.Equals(drFromObj, drFromSQL);
My question was going to be, 'How do other people deal with reality in a safe and sane manner?' I was also going to rule out converting to strings or writing my own DataRowComparer. I was going to offer that, in absence of better advice, I would change the 'set' on all of my DateTime properties to convert to a System.Data.SqlTypes.SqlDateTime and back upon storage thusly:
public Nullable<DateTime> InsertDate
{
get
{
if (_InsDate.HasValue)
return _InsDate;
else
return null;
}
set
{
if (!object.ReferenceEquals(null, value) && value.HasValue)
_InsDate = (DateTime)(new System.Data.SqlTypes.SqlDateTime(value));
}
}
I know full well that this would probably get screwed up as I used the _InsDate variable directly somewhere rather than going through the property. So my other suggestion was going to be simply using System.Data.SqlTypes.SqlDateTime for all properties where I might want a DateTime type to round trip to SQL Server (and, happily, SqlDateTime is nullable). This post changed my mind, however, and seemed to fix my immediate problem. My new question is, 'What are the caveats or real world experiences using the SQL Server datetime2(7) data type rather than the good, old datetime data type?'
TL;DR: Comparing dates is actually hard, even though it looks easy because you get away with it most of the time.
You have to be aware of this issue and round both values yourself to the desired precision.
This is essentially the same issue as comparing floating point numbers. If two times differ by four nanoseconds, does it make sense for your application to consider them different, or the same?
For example, if two servers have logged the same event, searching for corresponding records, you wouldn't say "no that can't be the correct event because the time is wrong by 200 nanoseconds". Clocks can differ by that amount on two servers no matter how hard they try to keep their time synchronised. You might accept that an event seen on server A and logged with a time a couple of seconds after the time on server B might have been actually seen simultaneously or the other way around.
Note:
If you are comparing data which is supposed to have made some sort of round-trip out of the database, you may find it has been truncated to the second or minute. (For example if it has been through Excel or an old VB application, or been written to a file and parsed back in.)
Data originating from external sources is generally rounded to the day, the minute, or the second. (except sometimes logfiles, eventlogs or electronic dataloggers, which may have milliseconds or better)
If the data has come from SQL Server, and you are comparing it back to itself (for example to detect changes), you may not encounter any issues as they will be implicitly truncated to the same precision.
Daylight savings and timezones introduce additional problems.
If searching for dates, use a date range. And make sure you write the query in such a way that any index can be used.
Somewhat related:
Why doesn't this sql query return any results comparing floating point numbers?
Identity increments. Sort by Identity and you get insert order. You (can) control insert order.
I seriously doubt output would ever by out of order but if you don't trust it you can use #SeeMeSorted
DECLARE #SeeMeSort TABLE
( [ID] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](20) NOT NULL);
DECLARE #SeeMeSorted TABLE
( [ID] [int] primary key NOT NULL,
[Name] [nvarchar](20) NOT NULL);
insert into #SeeMeSort ([Name])
OUTPUT INSERTED.[ID], INSERTED.[name]
values ('fff'), ('hhh'), ('ggg');
insert into #SeeMeSort ([Name])
OUTPUT INSERTED.[ID], INSERTED.[name]
into #SeeMeSorted
values ('xxx'), ('aaa'), ('ddd');
select * from #SeeMeSorted order by [ID];

Error when trying to update values in database

I have the following c#/Query:
TrackDuration =TimeSpan.Parse( Request.Form["TrackDuration"].ToString());
string InsertQuery = string.Format("UPDATE tblTracks SET TrackLength={0}, TrackDuration='{1}', TrackName='{2}',TrackDescription='{3}',TrackMap='{4}',DifficultLevel={5},OverallHeight={6},IsCircular='{7}', ForBeginners='{8}',StartPoint='{9}',ParkingPlace='{10}',SeasonOfYear={11},TrackLocation={12}, Images='{13}' WHERE UserID={14}",
TrackLength, TrackDuration, TrackName, TrackDescription, TrackMap, DifficultID, OverallHeight, IsCircular, ForBeginners, StartPoint, ParkingPlace, SeasonID, AreaID, ImageList, UserID);
But I got this error message:
Syntax error in UPDATE statement
Syntax error (missing operator) in query expression
I realy tried to solve this, but I can't.
How can I fix this problem?
Update:
This is the value of the Query:
UPDATE tblTracks SET TrackLength=35, TrackDuration='02:30:00', TrackName='45',TrackDescription='<p>sometext.</p>
',TrackMap='f',DifficultLevel=3,OverallHeight=450,IsCircular='true', ForBeginners='false',StartPoint='<p>קיבוץיסעור </p>
',ParkingPlace='<p>כניסה לקיבוץ יסעור</p>
',SeasonOfYear=1,TrackLocation=3, Images='' WHERE UserID=1
The sql values types are:
TrackLength = number ; TrackDuration = date/time ; TrackName= string ;TrackDescription= string; TrackMap = string; DifficultLevel=number;OverallHeight=number;IsCircular=true/false;ForBeginners=true/false;
StartPoint=string; ParkingPlace=string; SeasonOfYear=number; TrackLocation=number;Images=string
'02:30:00' is not a correct value for datetime DB field, AFAIK. The default format is controlled by date format setting.
Additionally, '20130412' should work in any case, but for datetime field. You need to format the TrackDuration correctly or use CAST/CONVERT. As TimeSpan doesn't contain date part (it represents a duration and not a point in time), you can only make it up (e.g. prepend "20100101") but that is an awful hack.
The proper solution is to use the correct DB field type.
'02:30:00' might work if the field was of time type. Please read some more about time types in SQL Server.
Even better, why don't you use plain integer for the duration in seconds? The duration is not a date anyway.
The much bigger issue is that you are concatenating strings to set the command text, which opens you for SQL injection attack. If I name the racing track a';DROP TABLE tblTracks;-- your database is toast:
UPDATE tblTracks SET TrackLength=35,
TrackDuration='02:30:00',
TrackName='a';DROP TABLE tblTracks;-- ...

Categories

Resources