Creating Breeze.js query with DateTimeOffset fails - javascript

I am running Breeze.WebApi v1.2.5 and I am also having problems with querying DateTimeOffset types.
Here is my query:
var query = entityQuery.from('Sessions')
.where('startTime', ">", new Date(2013, 3, 19));
This generates
http://localhost/api/breeze/Sessions?$filter=StartTime%20gt%20datetime'2013-04-19T05%3A00%3A00.000Z'
Which throws an error.
However, if I manually change the above generated query to use datetimeoffset (instead of datetime) Like so:
http://localhost/api/breeze/Sessions?$filter=StartTime%20gt%20datetimeoffset'2013-04-19T05%3A00%3A00.000Z'
It queries correctly and returns the appropriate response.
How can I get breeze to generate the appropriate query with datetimeoffset, instead of datetime?

As of v 1.2.7, this has been fixed
--- previous post
Ok, I've repro'd this. We should have a fix in the next release. I will post back here when it is released. and thx for finding it.

Related

How to send date with gremlin javascript

I think I'm missing something about the new javascript gremlin client.
I can't find any way to send any kind onf date from my script to the database.
Code example :
import { P } from 'gremlin/lib/process/traversal':
import g from '../path/to/my/gremlin/client';
const myFunction = id => g.V(id).has('some_date', P.gte(new Date())
In this code example I send a javascript date object. I tried a formated string, a timetamp, a stringified timestamp, and one exotical things.
And I always end up wwith an error like this one :
Error: Server error: java.lang.String cannot be cast to java.util.Date (500)
Or this one when I try with a number
Error: Server error: java.lang.Integer cannot be cast to java.util.Date (500)
Is there anything I can do ?
Regards,
F.
I'd suggest storing your Date as a String in your graph using ISO-8601 format. Then you should have no type transformation problems from Javascript as you'll just be sending strings in your Gremlin.
You have to be somewhat aware of the data types you have in your graph versus the ones you have in the target programming language you're using. Unfortunately, there aren't always one-to-one mappings to all the possible types that can be stored in a Java-based graph database (e.g. javax.time.*). For the most portable code and data, try to stick to the primitive types.

Breezejs automatic GUID parsing

I am using Breezejs in 'NoDB' mode, meaning I write my metadata by hand. When I create a Breeze query with OData parameters I add a filter by id, say
new breeze.Predicate('iD', datacontext.breeze.FilterQueryOp.Equals, myId)
The var myId is indeed a GUID value (though it's defined as a String), but in my DB and in both my server-side and client-side model it's a string (I can't change the DB structure). the property definition in my metadata model is
dataProperties: {
...
iD: { dataType: DataType.String },
...
}
(I know the property name looks weird, but I have to use this syntax since I have the breeze.NamingConvention.camelCase.setAsDefault() on my datacontext, and the property's name on the DB is ID uppercased)
When I execute the query I see that the corresponding oData filter option in the WebAPI url is like
$filter=ID eq guid'65BEB144-5C0C-4481-AC70-5E61FDAA840D'
which leads me to this server error: No coercion operator is defined between types 'System.Guid' and 'System.String'.
Is there a way to disable this automatic 'parsing' of GUIDs and leave them as strings?
I have temporarily solved this by removing the parsing directly inside breeze's source code so that my webAPI call would look like
$filter=ID eq '65BEB144-5C0C-4481-AC70-5E61FDAA840D'
but I don't like this solution and I would be glad if there was a better one, like parametrize this behaviour in some way. I didn't find anything about this on Breeze's official website.
Breeze uses its metadata to determine that datatype of each property in a query and then uses this information to generate the correct OData filter. So your metadata definition of ID as a string should be correct.
However, in order to perform this operation breeze needs to know the EntityType of your query. For example in the following query
var q = EntityQuery.from("Foo").where(....)
breeze needs to know the EntityType that "Foo" ( a resourceName) corresponds to. Once it has the entity type it can correctly format any filters for specific properties of this entityType. If breeze does not have 'EntityType', then it falls back to guessing about the datatype of each property. In your case, its guessing that the datatype is a 'Guid'
So the fix is to either tell the query directly about the EntityType that you are querying
var q = breeze.EntityQuery.from("Foo).where(....).toType(FoosEntityType);
or you can handle it more globally via via the MetadataStore.setEntityTypeForResourceName method.
breeze.MetadataStore.setEntityTypeForResourceName("Foo", FoosEntityType);
var q = breeze.EntityQuery.from("Foo).where(....); // your original query

OData Date Filtering from JS

I am using the DXTREME framework from Devexpress to connect a HTML mobile app to an OData source.
One of my tables in SQL Server, exposed through the OData service is a table with a date (not datetime) field in it. It is exposed through OData like this:
<d:TaskDate m:type="Edm.DateTime">2010-04-01T00:00:00</d:TaskDate>
I am trying to filter the data on this field through a calendar control, but when I try to filter the datasource on the JS side, I get no matches. This is because the date is passed to the OData service, I believe, in UTC format, so if I query for TaskDate = '10/JUL/2013', I believe the date is passed as "09/JUL/2013 14:00". If I filter on TaskDate > '10/JUL/2013' I get results back from after "09/JUL/2013 14:00" at any rate.
I have tried declaring a new date with no time part:
filterDate = new Date(2013, 6, 10)
but is still doesn't work, it still subtracts 10 formy time zone on the JS side.
What I want to do is to return a lists of Tasks valid on that particular date. How can I achieve this?
I think my problem was the confusion around the dxDateBox control returning just a date, and that date being changed when passed to my odata service.
I solved the issue by converting the date to UTC myself, but just using the Date parts from the control, (where filterDate came from the control):
var paramDate = new Date(Date.UTC(this.filterDate().getFullYear(), this.filterDate().getMonth(), this.filterDate().getDate()));
this.dataSource.filter(["TaskDate", "=", paramDate]);
This works nicely, but seems rather verbose.

How I handle JSON dates returned by ASP.NET AJAX?

The problem of how to handle dates in JSON is one of the more troublesome issues that may arise when directly calling ASP.NET AJAX web services and page methods.
Unlike every other data type in the language, JavaScript offers no declarative method for expressing a Date. Consequently, embedding them within JSON requires a bit of fancy footwork.
I will attempt to explain what exactly the problem is with dates in JSON.
What’s the problem?
The fundamental problem is that JavaScript does not provide a way to declaratively express Date objects. You may previously have seen this described as (the lack of) a Date literal.
What are literals? To illustrate, these are literals for several other data types:
// String
'foo';
// Number
3.14;
// Boolean
true;
// Array
[1, 2, 3, 5, 7];
// Object
{ pi: 3.14, phi: 1.62 };
Unfortunately, when it comes to dates, the lack of a literal means that the only way to create one is by explicitly initializing a Date object:
// Correct.
new Date('4/26/09');
// Correct (the month is 0 indexed, hence the 3).
new Date(2009, 3, 26);
// Incorrect. This is a string, not a Date.
'4/26/09';
While this limitation is fine when writing client-side JavaScript code, it leaves us without a good way to transmit dates within JSON objects.
lack of a date literal is a problem, Can Somebody Suggest a Solution.
Consider why you want to send a DateTime to the client-side to begin with. Most often, you’re displaying a string representation of it and have no need for the proper JavaScript Date object.
What’s more, if you end up with a JavaScript Date object, you’ll probably use additional code or a JavaScript library to display it in a user-friendly format.
As much as I appreciate a clever workaround, I’d much rather avoid the problem completely. Rather than jump through all of these hoops to instantiate a JavaScript Date object on the client-side and then format it, I suggest simply returning a formatted string.
For example,
[System.Web.Script.Services.ScriptService]
public class DateService : System.Web.Services.WebService
{
[WebMethod]
public string GetDate()
{
return new DateTime(2009, 4, 26).ToLongDateString();
}
}
Now, calling the service will return this JSON:
{"d":"Sunday, April 26, 2009"}
No more regular expressions. No more JavaScript Date objects. No more worrying about formatting the data on the client-side.
Even better, no functionality is lost. If we need to instantiate Dates, we still can.
I recently wrote a blog post about this sort of thing here... it's a minefield! At work, we've decided to transmit DateTimes and DateTimeOffsets from our MVC3 service as strings, using variations on a W3C format found here. For DateTime, we use YYYY-MM-DDThh:mm:ss, for DateTimeOffsets, YYYY-MM-DDThh:mm:ss+TZD (these format specifiers are W3C, not .NET).
But the answer to this question really does depend on what you want to do with the dates. As another reply suggests, you might be able to get away with simply sending a human readable string across the wire if all you want to do is display it to an end user.
I use two ways, one is to make it Date.UTC() and the other to make it as Ticks. Both they work.
The function that convert it to Json Ticks
private static readonly long UnixEpochTicks = (new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).Ticks;
  public static long cOnlyDate(long Ticks)
  {
    return (864000000000 * (Ticks / 864000000000));
  }
public static long ToJsonTicks(DateTime value)
{
return (cOnlyDate(value.ToUniversalTime().Ticks) - UnixEpochTicks) / 10000;
}
The results will be like {dt : 28839281}
and how I convert it to Date
public static string ToJsonDate(DateTime value)
{
return string.Format("Date.UTC({0}, {1}, {2})", value.Year, value.Month-1, value.Day);
}
The results will be like {d : Date.UTC(2012, 2, 11)}
ps, I just test now the solution of the "Unknow" and not work on my code.

Creating a BIRT Data Set with Dynamic Data - ORA-01722

Having some trouble getting BIRT to allow me to create a Data Set with Parameters that are set at run time.
The SQL that is giving me the error is:
...
FROM SPRIDEN, SPBPERS P, POSNCTL.NBRJOBS X, NHRDIST d1
where D1.NHRDIST_PAYNO between '#PAYNO_BEGIN' and '#PAYNO_BEGIN'
AND D1.NHRDIST_YEAR = '#YEAR'
...
I have my Report Parameters defined as PaynoBegin, PaynoEnd, Year
I also have a Data Set script set for beforeOpen as follows:
queryText = String (queryText).replace ("#PAYNO_END", Number(params["PaynoEnd"]));
queryText = String (queryText).replace ("#PAYNO_BEGIN", Number(params["PaynoBegin"]));
queryText = String (queryText).replace ("#YEAR", Number(params["Year"]));
The problem seems to be that the JDBC can't get the ResultSet from this, however I have 10 other reports that work the same way. I have commented out the where clause and it will generate the data set. I also tried breaking the where clause out into two and clauses with <= and >=, but it still throws a ORA-01722 invalid number error on the line.
Any thoughts on this?
Two quite separate thoughts:
1) You have single quotes around each of your parameters in the query, yet it appears as though each one is a numeric - try removing the single quotes, so that the where clause looks like this:
where D1.NHRDIST_PAYNO between #PAYNO_BEGIN and #PAYNO_BEGIN
AND D1.NHRDIST_YEAR = #YEAR
Don't forget that all three parameters should be required. If the query still returns an error, try replacing #PAYNO_BEGIN, #PAYNO_BEGIN and #YEAR with hardcoded numeric values in the query string, and see whether you still get an error.
2) You are currently using dynamic SQL - amending query strings to replace specified markers with the text of the entered parameters. This makes you vulnerable to SQL Injection attacks - if you are unfamiliar with the term, you can find a simple example here.
If you are familiar with the concept, you may be under the impression that SQL Injection attacks cannot be implemented with numeric parameters - Tom Kite has recently posted a few articles on his blog about SQL Injection, including one that deals with a SQL Injection flaw using NLS settings with numbers.
Instead, you should use bind parameters. To do so with your report, amend your query to include:
...
FROM SPRIDEN, SPBPERS P, POSNCTL.NBRJOBS X, NHRDIST d1
where D1.NHRDIST_PAYNO between ? and ?
AND D1.NHRDIST_YEAR = ?
...
instead of the existing code, remove the queryText replacement code from the beforeOpen script and map the three dataset parameters to the PaynoBegin, PaynoEnd and Year report parameters respectively in the Dataset Editor. (You should also change any other replaced text in your query text to bind parameter markers (?) and map dataset parameters to them as required.)

Categories

Resources