Notsupportedexception was unhandled by user code - c#

My code:
i f(!string.IsNullOrWhiteSpace(gender))
if (gender == "NULL")
predicate = predicate.And(x => string.IsNullOrWhiteSpace(gender));
else
predicate = predicate.And(x => x.Gender == gender);
When gender is NULL and when I am executing the flowing line:
var filteredUsers = _personExtendedRepository.GetMany(predicate).ToList();
an error occurs:
"LINQ to Entities does not recognize the method 'Boolean IsNullOrWhiteSpace(System.String)' method, and this method cannot be translated into a store expression."
Note:
When I am executing the following line in SQL Server Management Studio:
SELECT * FROM UVW_Sample WHERE Gender IS NULL
Records are displaying. Please help how to solve this issue.

LINQ-to-Entities is limited in what it can do, as it translates your expression to SQL, and it doesn't know how to translate string.IsNullOrWhiteSpace to SQL. It also doesn't know how to translate .ToString() to SQL.
What you need to do is perform the translation outside LINQ-to-Entities. In your case, your predicate should be:
x=>x==null || x.Trim()==""

string.IsNullOrWhiteSpace cannot be translated into SQL, so if you want to check whether column is null use something like:
predicate = predicate.And(x => x.Gender == null);

Related

LINQ expression could not be translated

I have the following database query where I am trying to check if there exists an item with a particular barcode that is linked to a particular mailbag. The query is as follows:
var exists = await dbcontext.Items
.Include(t => t.MailBagItems)
.ThenInclude(mt => mt.MailBag)
.AnyAsync(t => t.Barcode.Equals(barcode) &&
t.MailBagItems.FirstOrDefault() != null &&
t.MailBagItems.FirstOrDefault().MailBag.Number.ToLower().Equals(mailbagNumber.ToLower()));
For some reason, I'm getting the following exception:
System.InvalidOperationException: The LINQ expression could not be
translated. Either rewrite the query in a form that can be translated,
or switch to client evaluation explicitly by inserting a call to
either AsEnumerable(), AsAsyncEnumerable(), ToList(), or
ToListAsync().
I know for a fact from removing parts of the boolean expression that the issue is in the last boolean condition where I'm checking the mailbag number. However, I get the same error if I remove the calls to ToLower(). Can someone indicate what is wrong with my expression and how to fix it? Please note I'm using .NET core 3 and SQL Server.
Managed to make the query work by changing it to the following:
var exists = dbcontext.Items
.AnyAsync(t => t.Barcode.Equals(barcode) &&
t.MailBagItems.Any(t => t.MailBag.Number.ToLower().Equals(mailbagNumber.ToLower())));
Seems it wasn't enjoying the .FirstOrDefault().MailBag before.
Your AnyAsync is to complex for EF to transform to SQL, if you want to still use that query you will have to materialize the entities first, like this:
var exists = dbcontext.Items
.Include(t => t.MailBagItems)
.ThenInclude(mt => mt.MailBag)
.ToListAsync()
.AnyAsync(t => t.Barcode.Equals(barcode) &&
t.MailBagItems.FirstOrDefault() != null &&
t.MailBagItems.FirstOrDefault().MailBag.Number.ToLower().Equals(mailbagNumber.ToLower()));
Also you are missing the await keyword, or was that intended?

How can I query a database with LINQ when the column is a number but I have a string in the WHERE?

I am using this code:
query = String.IsNullOrEmpty(options.PhraseNum) ?
query :
query.Where(w => w.PhraseNum == Convert.ToInt32(options.PhraseNum));
However I get an error:
LINQ to Entities does not recognize the method 'Int32 ToInt32(System.String)' method, and this method cannot be translated into a store expression.
Is there a way I can do this in LINQ and if not how can I convert outside of this and have the conversion not cause an exception if the string is not null?
Only modify query if the string can be parsed to an int, which is an implicit check if it isn't null or empty:
if (int.TryParse(options.PhraseNum, out var phraseNum))
{
query = query.Where(w => w.PhraseNum == phraseNum);
}
Before C# 7 the syntax was
int phraseNum;
if (int.TryParse(options.PhraseNum, out phraseNum))
etc.
It looks like LINQ is trying to evaluate the expression Convert.ToInt32(options.PhraseNum) on the server side as part of the WHERE clause.
Redo the code so that the variable is cast explicitly on the client-side outside the query expression:
Int32 phrase_num = String.IsNullOrEmpty(options.PhraseNum) ? 0 : Convert.ToInt32;
query = String.IsNullOrEmpty(options.PhraseNum) ? query : query.Where(w => w.PhraseNum == phrase_num);
Or for a tidier approach overall:
if(!String.IsNullOrEmpty(options.PhraseNum))
{
Int32 phrase_num = Convert.ToInt32(options.PhraseNum);
query = query.Where(w => w.PhraseNum == phrase_num);
}
I think that should resolve the problem and preserve the intended program logic.
EDIT: I'd endorse Gert Arnold's approach above if you are using the latest C# version, where out parameters can be declared inline in the TryParse method call itself.

NHibernate QueryOver NullReferenceException

I have following QueryOver which throws NullReferenceException when newExam.ActiveTo is null (ActiveTo type is DateTime?)
Exam examAlias = null;
examsInSameTime = session.QueryOver(() => examAlias)
.Where(() => examAlias.ActiveTo == null && newExam.ActiveTo == null)
.Future<Exam>();
When I rewrote query to this HQL everything works fine
var query = "from Exam exam where exam.ActiveTo is null and :newExamActiveTo is null)";
examsInSameTime = session.CreateQuery(query)
.SetParameter("newExamActiveTo", newExam.ActiveTo).List<Exam>();
Why QueryOver throws exception and HQL not?
I would say, that solution here should be surprisingly simple and elegant (but only if I do read your issue correctly).
The point is - check your params in C#, do not send that into DB side:
Exam examAlias = null;
var query = session.QueryOver(() => examAlias);
//here we will check what needed
if(newExam.ActiveTo == null)
{
query.Where(() => examAlias.ActiveTo == null)
}
// we can repeat that many times and build WHERE clause as required
...
// finally the query
examsInSameTime = query.Future<Exam>();
So, the trick here is:
check the search params on application side
if needed, convert them into SQL WHERE statement
send on DB side only restrictions which are required
As written by Radim, you are using a parameter inside the QueryOver. The problem is that newExam is probably null when you execute the query.

LINQ to Entities does not recognize the method IsNullOrWhiteSpace

I have the below code:
var countries = from c in db.Countries
where (string.IsNullOrWhiteSpace(searchAlpha2) || (c.Alpha2 ?? string.Empty).ToUpper().Contains(searchAlpha2.ToUpper()))
&& (string.IsNullOrWhiteSpace(searchAlpha2) || (c.Alpha3 ?? string.Empty).ToUpper().Contains(searchAlpha3.ToUpper()))
&& (string.IsNullOrWhiteSpace(searchName) || (c.Name ?? string.Empty).ToUpper().Contains(searchName.ToUpper()))
select c;
This code uses Entity Framework v6 Code First over a SQL database.
Aside from performance, if I don't include the IsNullOrWhitespace I get no results when the filter criteria are blank (I've tested both null and blank values); however when a value is present this works as expected.
I'm getting the error:
LINQ to Entities does not recognize the method 'Boolean IsNullOrWhiteSpace(System.String)' method, and this method cannot be translated into a store expression.
I'm trying to use the searchXXX strings to filter on columns. I've tried using RegEx.IsMatch, SqlMethods.Like, and the code below, but all give me errors saying those functions are not allowed (errors come from either EntityFramework.SqlServer or from Linq to Entities). I've seen numerous posts on here where this has been done successfully though - so wonder if I'm missing something fundamental?
If you want to use your statement in current form you might want to replace
string.IsNullOrWhiteSpace(searchAlpha2)
to
!(searchAlpha2 == null || searchAlpha2.Trim() == string.Empty)
and all the other values too, for it to get translated to working SQL.
Update: Copied from comment by #DavidKempfner
As of EntityFramework.6.2.0 it generated SQL that checked for
!(searchAlpha2.Trim() == string.Empty),
I.E. It ignored the searchAlpha2 == null || part.
Use this instead:
!string.IsNullOrEmpty(entity.searchAlpha2.Trim())
I would suggest a different approach - use the ability to build queries up on the fly, and thus avoid passing optional query parameters to the expressions altogether - this will result in improved query plans when parsed to sql and executed on the database.
Also, if your database (?SqlServer) is not set to case sensitive collation (i.e. xx_CI_xx), you can avoid the casing conversion as well, as it is redundant:
var myQueryable = db.Countries.AsQueryable();
if (!string.IsNullOrWhiteSpace(searchAlpha2))
{
myQueryable = myQueryable.Where(c => c.Alpha2.Contains(searchAlpha2));
}
...
var countries = myQueryable.ToList();
You can get this and a bunch more functionality using PredicateBuilder
Update
JB: based on StuartLC's answer, here's the code amended to use PredicateBuilder:
var predicate = PredicateBuilder.True<Country>();
if (!string.IsNullOrWhiteSpace(searchAlpha2))
predicate = predicate.And(c => c.Alpha2 != null ? c.Alpha2.Contains(searchAlpha2) : false);
if (!string.IsNullOrWhiteSpace(searchAlpha3))
predicate = predicate.And(c => c.Alpha3 != null ? c.Alpha3.Contains(searchAlpha3) : false);
if (!string.IsNullOrWhiteSpace(searchName))
predicate = predicate.And(c => c.Name != null ? c.Name.Contains(searchName) : false);
IQueryable<Country> countries = db.Countries.AsExpandable().Where(predicate);
when you use linq in Entity Framework to get data from DataBase you need to use only with functions that the Entity Framework can convert to sql query.
I know that there an already accepted answer for this question but I got an idea to share.
Instead of putting multiple checks in the LINQ or using if statement to apply where clause on list result, you can use a simple trick. Just declare a bool variable and assign IsNullOrWhitespace of add to linq like:
bool isNull = string.IsNullOrWhiteSpace(searchAlpha2);
var countries = db.Countries.Where(c => isNull || c.Alpha2.Contains(searchAlpha2)).ToList();

Entity Framework ToString method

Following code block throws error.
LINQ to Entities does not recognize the method 'System.String ToString()' method, and this method cannot be translated into a store expression.
db.tbOnIgmHawbDetails
.Where(s => !db.tbImpoExaminations.Any(x => x.Hawb.ToString() == s.Hawb) && s.AwbNo == p)
.Select(s => s.Hawb).ToList();
Any suggestion? why this happen and what is the solution?
.ToString() is supported properly going forward with EF 6.1: http://blogs.msdn.com/b/adonet/archive/2014/03/17/ef6-1-0-rtm-available.aspx
You could try with SqlFunctions.StringConvert... Use the decimal conversion:
SqlFunctions.StringConvert((decimal)p.x.Hawb).TrimLeft() == ...
(the TrimLeft is necessary because the STR function of SQL will right align the number)
If s.Hawb is already string type (the error message suggests so), then remove the part .ToString() from your query.
The reason for it is that in LINQ2SQL, you can only use those language constructs that can be translated into SQL. For example, if you try to use RegEx in your C# expression, then SQL does not have a corresponding construct for RegEx, and thus LINQ cannot translate and execute your query.
Easily add .AsEnumerable() before the .ToString() and those methods that L2E doesn't support:
var asen = db.tbOnIgmHawbDetails.AsEnumerable();
var result = asen.Where(s => !asen.Any(x => x.Hawb.ToString() == s.Hawb) && s.AwbNo == p)
.Select(s => s.Hawb).ToList();
That should works. However if not, try to perform your query by linq-to-objects syntax:
var result = from a in asen
where ...
select ...;
do not use ToString
just use like
x.Hawb + "" == s.Hawb

Categories