Entity Framework search expression - entity-framework

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.

Related

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") });

Linq To Entities - run CONVERT to int on DB

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"

EF 4.1 Linq Predicate Contains Generates desired SQL when using hard-coded string but not with string variable

I have this code:
string name ="M";
Expression<Func<Organization, bool>> getExpression1 = r => r.Name.Contains(name);
Expression<Func<Organization, bool>> getExpression2 = r => r.Name.Contains("M");
GetOrgListBy(getExpression);
GetOrgListBy(getExpression2);
public IEnumerable<Organization> GetOrgListBy(Expression<Func<Organization, bool>> filter)
{
return DataContext.Parties.OfType<Organization>().Where(filter).ToList();
}
Question:
I am passing a simple expression to a repository function
that gets List<Organization> by matching the name passed.
When I view the sql trace for getExpression1 (uses a string variable), the expression generates a [Name] like plinq_variable sql statement
which omits the % operator. My intention is to generate a
[Name] like '%' + plinq_variable + '%' sql statement
However, when I when using getExpression2 (hard-coded the string), the expression successfully
generates a [Name] like N'%M%' sql statement.
Why doesn't getExpression1 generate the % operator?
How can I make it generate a % operator in the sql just like getExpression2?
The first expression translates into a parametrized SQL query. The variable in the Where clause ...
[Name] like plinq_variable
... is set to the value
#plinq_variable=N'%M%'
when the query is executed. The second expression translates to a SQL query with a hardcoded string literal:
[Name] like N'%M%'
Then this query is directly executed.
The result for both expressions and queries is the same.

JPA Native Query

I am trying to execute a native query and pass run-time parameters and get the result as a List. When I try to process the Object [], one of the columns fetched is a String. But it comes out as java.lang.Character instead of String. Here is the query below:
SELECT CASE
WHEN (TRUNC(abm.credit_card_expiration_date) BETWEEN trunc(SYSDATE) AND
trunc(last_day(SYSDATE))) THEN
'Expires'
ELSE
'Expired'
END EXP_STATUS,
TO_CHAR(abm.credit_card_expiration_date, 'MM/YY') EXP_DATE
FROM account_billing_methods abm
WHERE abm.account_id = 201103
AND abm.billing_type_id = 1
AND TRUNC(abm.credit_card_expiration_date) <= TRUNC(LAST_DAY(SYSDATE))
The EXP_STATUS column could not be typecasted into String as it is of type Character. Any ideas of why it does not work?
Regards,
-Anand
I had the same problem and changed the select clause of my query to:
EXP_STATUS || '' as EXP_STATUS
Then it is a VARCHAR instead of a CHAR and JPA will return it as a String instead of a Character.
If someone knows a better/more elegant solution, I would appreciate if you could share it.

Zend Framework: Re-use WHERE clause returned from Zend_Db_Select::getPart()

I have a SELECT object which contains a WHERE.
I can return the WHERE using getPart(Zend_Db_Select::WHERE), this returns something like this:
array
0 => string "(clienttype = 'agent')"
1 => string "AND (nextpayment < (NOW() - INTERVAL 1 DAY))"
This array seems pretty useless as I cannot do this with it
$client->update(array("paymentstatus" => "lapsed"), $where);
Or even put it into another SELECT object. Is there a way of getting a more useful representation of the WHERE statement from the SELECT object?
Thanks
EDIT
The best I have come up with so far is
$where = new Zend_Db_Expr(implode(" ", $select->getPart(Zend_Db_Select::WHERE)));
Your first choice, $client->update(...) would work, if getParts omitted the 'AND' from the second part of the where clause.
I'm pretty sure your only choice is to:
use your second option (probably safest depending on how complex the where clauses are) -or-
iterate through the $where returned and remove the leading 'AND', 'OR' that may exist.