Breeze / breeze-client

Breeze for JavaScript clients
MIT License
38 stars 16 forks source link

Number is sent as Double to server #40

Closed graphicsxp closed 3 years ago

graphicsxp commented 3 years ago

When building a query with a literal predicate, if the value is a number, breeze sends the dataType as double. This happens here, line 238.

Capture d’écran 2021-03-24 154613

image

Ending up with this error from server side (breeze .net core 3)

image

This is how my predicate is created :
return Predicate.and(new Predicate("RemainingPercentage", "eq", { value: this.value , isLiteral: true } ));

I could change this code to

return Predicate.and(new Predicate("RemainingPercentage", "eq", { value: this.value , dataType: breeze.DataType.Decimal} ));

but I don't want to hardcode it as it needs to remain generic.

Could numbers be sent as decimal ? Or do I need to explicitly set the data type ?

steveschmitt commented 3 years ago

I can't reproduce this. When I use:

new Predicate("freight", "eq", { value: freightValue , isLiteral: true })

Breeze sends the query to the server with:

{"where":{"Freight":{"value":500,"dataType":"Decimal"}}}

I think Breeze gets the dataType from the metadata for the entity property. What does your metadata have for RemainingPercentage?

steveschmitt commented 3 years ago

@graphicsxp Any more clues about this one?

graphicsxp commented 3 years ago

@steveschmitt the metadata are :

image

As you can see, it is a decimal so I would excpect breeze to query using the Decimal type. I don't why you cannot reproduce this issue.

I'm using breeze-client 2.0.11.

When I call executeQuery, the json query is built and when it reaches the below code in data-types.ts, the value (23 in this case) is considered as a Double (I don't even see Decimal in the switch statement)

image

I don't know how it is possible that we have a different behavior for this use-case :(

steveschmitt commented 3 years ago

In my case, fromValue() is not called, because the DataType is known already.

During the creation of the where clause, the Predicate is converted to JSON, and this _validate function is called:

image

In the code above, the createExpr function creates the predicate expression using the DataType for the property, which it gets from the EntityType.

I don't know why you are not getting the DataType from the _validate function.

steveschmitt commented 3 years ago

Perhaps the problem is the same as in #47 : Breeze does not know the EntityType for the query endpoint, so it can't determine the DataType.

I tried it again, using the same predicate:

var freightValue = 388.98;
var pred = Predicate.create("freight", "eq", { value: freightValue , isLiteral: true })

If I use the standard endpoint for the Order entity, then it works fine:

var query = EntityQuery.from("Orders").where(pred); // query has "dataType": "Decimal"

But if I change the endpoint to "OrdersAgain", which is not in the metadata, then Breeze has to guess the datatype:

var query = EntityQuery.from("OrdersAgain").where(pred); // query has "dataType": "Double"

The fix is to use toType so that Breeze knows the EntityType and can determine the DataType of the property:

var query = EntityQuery.from("OrdersAgain").toType("Order").where(pred); // query has "dataType": "Decimal"

Hope this helps.