Linq To Entities - run CONVERT to int on DB - entity-framework

My table in DB contains varchar field which contains both string and integer values. Requirement is compare only integers with provided value.
This code
from c in Cars
where SqlFunctions.IsNumeric(c.Code)
&& Convert.ToInt32(c.Code) == 12
throws
LINQ to Entities does not recognize the method 'Int32 ToInt32(System.String)' method, and this method cannot be translated into a store expression.
Runing this query in LINQPad is working fine! Why?
Question: How to Convert string directly in db and compare with provided integer value.

Why not just:
from c in Cars
where c.Code == "12"

Related

Text and jsonb concatenation in a single postgresql query

How can I concatenate a string inside of a concatenated jsonb object in postgresql? In other words, I am using the JSONb concatenate operator as well as the text concatenate operator in the same query and running into trouble.
Or... if there is a totally different query I should be executing, I'd appreciate hearing suggestions. The goal is to update a row containing a jsonb column. We don't want to overwrite existing key value pairs in the jsonb column that are not provided in the query and we also want to update multiple rows at once.
My query:
update contacts as c set data = data || '{"geomatch": "MATCH","latitude":'||v.latitude||'}'
from (values (16247746,40.814140),
(16247747,20.900840),
(16247748,20.890570)) as v(contact_id,latitude) where c.contact_id = v.contact_id
The Error:
ERROR: invalid input syntax for type json
LINE 85: update contacts as c set data = data || '{"geomatch": "MATCH...
^
DETAIL: The input string ended unexpectedly.
CONTEXT: JSON data, line 1: {"geomatch": "MATCH","latitude":
SQL state: 22P02
Character: 4573
You might be looking for
SET data = data || ('{"geomatch": "MATCH","latitude":'||v.latitude||'}')::jsonb
-- ^^ jsonb ^^ text ^^ text
but that's not how one should build JSON objects - that v.latitude might not be a valid JSON literal, or even contain some injection like "", "otherKey": "oops". (Admittedly, in your example you control the values, and they're numbers so it might be fine, but it's still a bad practice). Instead, use jsonb_build_object:
SET data = data || jsonb_build_object('geomatch', 'MATCH', 'latitude', v.latitude)
There are two problems. The first is operator precedence preventing your concatenation of a jsonb object to what is read a text object. The second is that the concatenation of text pieces requires a cast to jsonb.
This should work:
update contacts as c
set data = data || ('{"geomatch": "MATCH","latitude":'||v.latitude||'}')::jsonb
from (values (16247746,40.814140),
(16247747,20.900840),
(16247748,20.890570)) as v(contact_id,latitude)
where c.contact_id = v.contact_id
;

How to format a number in Entity Framework LINQ (without trailing zeroes)?

In a SQL Server database I have a column of decimal datatype defined something like this:
CREATE TABLE MyTable
(
Id INT,
Number DECIMAL(9, 4)
)
I use Entity Framework and I would like to return column Number converted to a string with only the digits right of the decimal separator that are actually needed. A strict constraint is that a result must be an IQueryable.
So my query is:
IQueryable queryable = (
from myTable in MyDatabase.NyTable
select new
{
Id = myTable.Id,
Number = SqlFunctions.StringConvert(myTable.Number,9,4)
}
);
The problem with is that it always convert number to string with 4 decimals, even if they are 0.
Examples:
3 is converted to "3.0000"
1.2 is converted to "1.2000"
If I use other parameters for StringConvert i.e.
SqlFunctions.StringConvert(myTable.Number, 9, 2)
the results are also not OK:
0.375 gets rounded to 0.38.
StringConvert() function is translated into SQL Server function STR.
https://learn.microsoft.com/en-us/sql/t-sql/functions/str-transact-sql?view=sql-server-2017
This explains the weird results.
In the realm of Entity Framework and LINQ I was not able to find a working solution.
What I look for is something like C# function
String.Format("0.####", number)
but this cannot be used in a LINQ query.
In plain simple SQL I could write my query like this
SELECT
Id,
Number = CAST(CAST(Number AS REAL) AS VARCHAR(15))
FROM
MyTable
I have not managed to massage LINQ to produce query like that.
A workaround would be to forget doing this in LINQ, which is quite inflexible and messy thing, borderline on useless and just return type DECIMAL from database and do my formatting on a client side before displaying. But this is additional, unnecessary code and I would hate to di it that way if there perhaps is a simpler way via LINQ.
Is it possible to format numbers in LINQ queries?
I would absolutely return a decimal from he database and format it when needed. Possible directly after the query. But usually this is done at display time to take into account culture specific formatting from the the client.
var q =
(from myTable in MyDatabase.NyTable
select new
{
Id = myTable.Id,
Number = myTable.Number
})
.AsEnumerable()
.Select(x => new { Id = x.Id, Number = x.Number.ToString("G29") });

Criteria Query using Postgres

Using :-
Postgres : PostgreSQL 10.0
Hibernate : 4.0.1
I have the following example table created in Postgres
CREATE TABLE Automobile
(id SERIAL
,name VARCHAR(20)
,year INTEGER
);
I have created a domain Automobile class.
I have the following hibernate criteria query to return all the names for a particular year.
final Criteria criteria = session.createCriteria (Automobile.class);
criteria.add (Restrictions.eq ("year", 1 ));
List<Automobile> list = criteria.list();
However, the list() is generating the following exception.
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
So I changed query to pass in a String value for the "year" :-
criteria.add (Restrictions.eq ("year", new String("1")));
List<Automobile> list = criteria.list();
However, the list() is generating a different exception.
org.hibernate.exception.SQLGrammarException: ERROR: operator does not exist: integer = character varying
Hint: No operator matches the given name and argument type(s). You might need to add explicit type casts.
Position: 1145
Any thoughts on what maybe the cause and solution that would return me list of matches please ?
Thank you
Pete.
In the Hibernate mapping you have
<property name="year" type="java.lang.String" >
You didn't show you Java code. I suppose year is also String there.
But in the database year is an integer.
Solution: Change your mapping as follows:
Also change your Java class and define year as Integer.

How to sort queries using string values of enum columns

my table contains int columns that correspons to enum types.
E.g. the values of int column Command corresponds to this type:
public enum Commands
{
Start = 1,
End = 2
}
If I query the table and order it by Command, I get the rows with Command=Start followed by Commen=End.
Is there a way I can sort the query by the string value of the Command column, e.g. End first and Start last.
results.OrderBy(s => (Command as Commands).ToString())
But it gives me error "Only initializers, entity members, and entity navigation properties are supported".
Of course I could put the Command's string value as a column and sort by it, but we prefer using int columns for different reasons.
Thanks

Entity Framework search expression

I have to make search through field EmployeeId.
I also have parameter empId which can be something like this: '123'
In my database there's next values:
'0123' - what I need
'10123'
'1234'
and so on.
My target - take a record which ends on empId and has no or one and more leading 0.
I tried to write something like this:
var result = from member in MembersSet
where SqlMethods.Like(member.EmployeeId, "%" + empId) &&
!(SqlMethods.Like(member.EmployeeId, "%[^0]%" + empId))
select member.Id;
But I get an error
LINQ to Entities does not recognize the method 'Boolean Like(System.String, System.String)' method, and this method cannot be translated into a store expression.
May be there is a workaround?
The SqlMethods is for Linq-To-Sql, not EntityFramework. There's an equivalent for EF - SqlFunctions (System.Data.Objects.SqlClient.SqlFunctions). You can use the PatIndex function to do what you want. It's worth noting that this will make your code SQL Server specific.
You can do the initial expression without using PatIndex by using the standard String EndsWith function, which will get translated by EF automatically.
var result = from member in MembersSet
where member.Id.EndsWith("123")
&& SqlFunctions.PatIndex("[^0]%123", member.Id) == 0
select member.Id;
If the values of Id will always be numeric (even with leading zeros), you could try converting them to Integers on the server, by defining an additional method to handle parsing to int (EF won't translate Int32.Parse) - see this question for details.