LINQ to Entities does not recognize the method 'Boolean ToBoolean [duplicate] - c#

This question already has an answer here:
LINQ to Entities does not recognize the method 'System.Web.Mvc.FileResult'
(1 answer)
Closed 7 years ago.
I have a class Like this :
public class menu{
public string Permission{get;set;}
}
The value Of Permission is Encripted . I want all records where Permission is True. To do this, I use this query :
return
_menuSettings.Where(row => Convert.ToBoolean(Utilities.Encryption.Decrypt(row.Permission,"key"))==true).ToList();
but I get this error :
LINQ to Entities does not recognize the method 'Boolean ToBoolean(System.String)' method, and this method cannot be translated into a store expression.
I searched on google, but I can't solve it .
thanks

What you are asking for cannot be achieved by db query. I'm afraid you are stuck with in memory filtering (hope your don't have too many records) like this
return
_menuSettings.AsEnumerable().Where(...
here AsEnumerable() will switch the context from Linq to Entities to Linq to Objects

Not every method is convertible to SQL thats the essence of that message.
In your case you can compare against the string "true".
_menuSettings.Where(row => Utilities.Encryption.Decrypt(row.Permission,"key").ToLower()=="true").ToList();
Now as mentioned the message means the method is not convertible to SQL. So then by no real surprise get that Utilities.Encryption.Decrypt is also not supported.
Then continue with the same concept of taking things that don't work, out of the query.
The quick and dirty way is to realize/project the data (use ToList() or ToIEnumerable() before you filter with the non-supported filter).
Meaning that you take everything out of the table and filter it on your server instead on the DBMS (SQL server).
Like this. (i have split it into more lines for readability)
var projection = _menuSettings.ToList();
var result = projection.Where(row => Utilities.Encryption.Decrypt(row.Permission,"key").ToLower()=="true").ToList();
A wise choice is to find a good way to limit the projection size before you do heavy work like this.

Related

LINQ to entities : cannot call a method

I'm aware there are alreay a lot of posts concerning this issue, but i can't seem to find a solution for this.
Here's my Ling to Entities query :
IEnumerable<Tblstamp> changes = (from c in userGSN.edb.Tblstamp
where (c.Ts_Date >= userGSN.DateLastCheck &&
TimeSpan.Parse(c.Ts_Time) >= userGSN.TimeLastCheck)
orderby c.Ts_Id ascending
select c);
I want to compare c.Ts_time to userGSN.TimeLastCheck, but for that I have to convert the c.Ts_Time to a timespan (it is a string, and comes from a database I can't modify, tried everything). I also can't do the converting before the query in an other variable since I can't access it outside of the query.
Obviously, I get an error for trying to use the TimeSpan.Parse method in my query, but I can't find any workaround to this. I have tried using LINQ to Object but since I am really not used to it I couldn't make the equivalent query that i have here.
I am aware of the problem, I'm just trying to find a workaround and need some help please !
EDIT :
So I tried the DateDiff function as suggested :
IEnumerable<Tblstamp> changes = (from c in userGSN.edb.Tblstamp
where (c.Ts_Date >= userGSN.DateLastCheck && SqlFunctions.DateDiff("second",userGSN.TimeLastCheck,c.Ts_Time).Value > 0 )
orderby c.Ts_Id ascending
select c
);
but it gives me the same error : "LINQ to Entities does not recognize the method 'System.Nullable1[System.Int32] DateDiff(System.String, System.Nullable1[System.TimeSpan], System.String)' method, and this method cannot be translated into a store expression."
Even though it clearly says here "You cannot call this function directly. This function can only appear within a LINQ to Entities query.", which is exactly what I'm doing ?!
There's no clean way to do this, so you'll have to think outside the box. Try using SqlFunctions.DateDiff to perform the check. You'll need to adapt it for your usage, but:
SqlFunctions.DateDiff("second", c.Ts_Time, userGSN.TimeLastCheck.ToString()) > 0
There are other methods that you can use, if DateDiff is not suitable. See EntityFunctions as well.
Depending on what you're using to query the data, you might want System.Data.Entity.SqlServer.SqlFunctions instead.
Every code you write in LinQ to get data from database must convert to a valid T-SQL query with valid statements. Not all C# methods have a correspondance in T-SQL so whenever you use them in your code while fatching data you will get errors.
You should either do modifications on the SQL side or use C# spesific functions after fething data from database, while working with entities in memory, or use fıunstions which comply with SQL statements.
If you can't get EF to translate your query to SQL, maybe you could do it yourself? See Writing SQL queries for entities
Linq to Entities does not support all functions since the query has to be translated to SQL:
from c in userGSN.edb.Tblstamp.AsEnumerable()
//now you are allready getting the data from the database
//so be carefull with that because you will have bad performance

Linq Approaches what is the difference? Talking About Caching [duplicate]

This question already has answers here:
Fluent and Query Expression — Is there any benefit(s) of one over other?
(14 answers)
Closed 8 years ago.
I'm a little (very) confused about the usage of the the following queries
This:
var query = from p in ctx.Persons
where x.Flat.Building.Id == 1 && x.Archived == false
select p;
And this:
var query = ctx.Persons.Where(x => x.Flat.Building.Id == 1 && x.Archived == false);
If I make some changes to the result of both queries and try to query them again, the 1st shows the old results, but the 2nd doesn't?
This answer tries to explain, but it is really confusing, at least for me.
EDIT
Maybe my question doesn't be so clear as I expect but I'm going to try to focus.
My exact problem is if I use Query Sintax and made some changes over the data, and query again it doesn't load the fresh data. But in This answer The autor talks about if use Fluent Sintax this doesn´t happen.
Now here is my nigthmare why this happens with Query Sintax and doesn't with Fluent sintax?
The first query it is exactly the same with the second query. The only difference between them is the syntax. In the first one you have the so called query syntax and in the second one you have the so called fluent (or method) syntax. Under the hood the first query, will be complied at the first step of complilation to the second query.
For more information about this, please have a look here. As it is stated there,
Query syntax and method syntax are semantically identical

LINQ to Entities does not recognize the method 'Int32 IndexOf(System.String, System.StringComparison)' method

I have executed a linq query by using Entityframework like below
GroupMaster getGroup = null;
getGroup = DataContext.Groups.FirstOrDefault(item => keyword.IndexOf(item.Keywords,StringComparison.OrdinalIgnoreCase)>=0 && item.IsEnabled)
when executing this method I got exception like below
LINQ to Entities does not recognize the method 'Int32 IndexOf(System.String, System.StringComparison)' method, and this
method cannot be translated into a store expression.
Contains() method by default case sensitive so again I need to convert to lower.Is there any method for checking a string match other than the contains method and is there any method to solve the indexOf method issue?
The IndexOf method Of string class will not recognized by Entity Framework, Please replace this function with SQLfunction or Canonical functions
You can also take help from here or maybe here
You can use below code sample:
DataContext.Groups.FirstOrDefault(item =>
System.Data.Objects.SqlClient.SqlFunctions.CharIndex(item.Keywords, keyword).Value >=0 && item.IsEnabled)
You really only have four options here.
Change the collation of the database globally. This can be done in several ways, a simple google search should reveal them.
Change the collation of individual tables or columns.
Use a stored procedure and specify the COLATE statement on your query
perform a query and return a large set of results, then filter in memory using Linq to Objects.
number 4 is not a good option unless your result set is pretty small. #3 is good if you can't change the database (but you can't use Linq with it).
numbers 1 and 2 are choices you need to make about your data model as a whole, or if you only want to do it on specific fields.
Changing the Servers collation:
http://technet.microsoft.com/en-us/library/ms179254.aspx
Changing the Database Collation:
http://technet.microsoft.com/en-us/library/ms179254.aspx
Changing the Columns Collation:
http://technet.microsoft.com/en-us/library/ms190920(v=sql.105).aspx
Using the Collate statement in a stored proc:
http://technet.microsoft.com/en-us/library/ms184391.aspx
Instead you can use this method below for lowering the cases:
var lowerCaseItem = item.ToLower();
If your item is of type string. Then this might get you through that exception.
Erik Funkenbush' answer is perfectly valid when looking at it like a database problem. But I get the feeling that you need a better structure for keeping data regarding keywords if you want to traverse them efficiently.
Note that this answer isn't intended to be better, it is intended to fix the problem in your data model rather than making the environment adapt to the current (apparently flawed, since there is an issue) data model you have.
My main suggestion, regardless of time constraint (I realize this isn't the easiest fix) would be to add a separate table for the keywords (with a many-to-many relationship with its related classes).
[GROUPS] * ------- * [KEYWORD]
This should allow for you to search for the keyword, and only then retrieve the items that have that keyword related to it (based on ID rather than a compound string).
int? keywordID = DataContext.Keywords.Where(x => x.Name == keywordFilter).Select(x => x.Id).FirstOrDefault();
if(keywordID != null)
{
getGroup = DataContext.Groups.FirstOrDefault(group => group.Keywords.Any(kw => kw.Id == keywordID));
}
But I can understand completely if this type of fix is not possible anymore in the current project. I wanted to mention it though, in case anyone in the future stumbles on this question and still has the option for improving the data structure.

How to get max value of a string column of numbers in Entity Framework [duplicate]

This question already has an answer here:
Convert String to Int in EF 4.0
(1 answer)
Closed 8 years ago.
I have a problem here. I was trying to get the max value of an sql field as,
LastInvoiceNo = Convert.ToInt64(dbContext.InvoiceMaster.Max(e => e.InvoiceNo));
But it gives me wrong value since the column type of "InvoiceNo" is varchar.
So I tried to convert it to Int64 as
LastInvoiceNo = dbContext.InvoiceMaster.Max(e =>Convert.ToInt64(e.InvoiceNo));
and
LastInvoiceNo = dbContext.InvoiceMaster.Select(e => Int64.Parse(e.InvoiceNo)).Max();
But it throws an exception that
LINQ to Entities does not recognize the method 'Int64 Parse(System.String)' method, and this method cannot be translated into a store expression.
The error you get is because EF is trying to translate your linq query to actual SQL statements, but it can't.
What you could do is bring the data locally by forcing the query to execute, and then you will be able to convert to Int64 and check for Max.
Something like this:
LastInvoiceNo = dbContext.InvoiceMaster.ToList().Max(e => Convert.ToInt64(e.InvoiceNo));
Not sure if that's the best thing to do if you have millions of rows in that table though.
Cheers
If you are working with MSSQL, you may try to use SqlFunctions static class that specially designed to be used in LINQ queries and to be translated to the native server functions. Looks a bit weird, but the following may work:
dbContext.InvoiceMaster.Max(e =>SqlFunctions.Replicate("0", 16-e.InvoiceNo.Length) + e.InvoiceNo);
What I'm trying to do here is to emulate PadLeft function that is not available in SqlFunctions, so having all strings normalized by the length you may select max value and then convert it to actual number.

How do I implement a search feature with Entity Framework?

I have a blog application that models a database using Entity Framework. The problem with this blog is that it has become difficult to find things I'm looking for. It needs a search function, but I'm not sure how to implement this with SQL and/or LINQ to Entities.
Right now I am searching my database with this LINQ query but it seems like it should be better.
public IEnumerable<BlogPost> SearchBlogPosts(string query, int page, int itemsPerPage)
{
var result = _dataContext.BlogPosts
.Where(BlogPostContains(query))
.OrderByDescending(x => x.PostedDate)
.Skip((page - 1) * itemsPerPage)
.Take(itemsPerPage),
return result;
}
private Func<BlogPost, bool> BlogPostContains(string query)
{
return x => x.Title.Contains(query) || x.Body.Contains(query) || x.Author.Contains(query);
}
One big problem with this is that the search is case sensitive.
Question 1) Is there a better way to do searching with LINQ to Entities?
Question 2) What about with just plain SQL? How would I write a search stored procedure in SQL Server so that I can map and use that in EF instead of LINQ?
I just want a case-insensitive search that is performed in the database so as to maintain good performance.
Thanks in advance.
The standard approach for this would be a SQL fulltext search. You will have to enable fulltext on the DB, designate column(s) to be fulltext indexed and then will then be able to use SQL Contains queries using these columns.
Fulltext search queries are currently not supported by Linq to Entities - you will have to resort to standard SQL queries for this. You can use ExecuteStoreQuery() to at least map the search results to typed result.
The default collation of SQL Server is case-insensitive which means that a where clause like this (which is what LINQ to Entities would create out of Contains)...
where Name like '%JOHN%'
...should find "john Wayne". I believe that your query is not executed on the server but actually with LINQ to Objects in memory - and there the search is case sensitive. It's LINQ to Objects because you are not returning an Expression from your BlogPostContains. The signature should be:
private Expression<Func<BlogPost, bool>> BlogPostContains(string query)
If your are only returning Func<BlogPost, bool> you are working with the IEnumerable (and not the IQueryable) overload of the Where extension method which in turn causes the whole BlogPosts table loaded first into memory. Then the filter is applied in memory with LINQ to Objects.
Would be interesting to know if the case-sensitivity disappears if you return an Expression.
(Just as a note about your Case-Sensitivity problem, not a solution to your general question about the best way to implement a Search feature.)
I would look at Lucene.Net for a good search provider.
As per your searches using LINQ, you can try something like this and it works just fine:
(x.Title).ToUpper().Contains(query.ToUpper())
Or the similar method of ToLower() should suffice as well.
For databases that truly consider an uppercase 'A' different from a lowercase 'a' as different values, which they are technically are, the above LINQ procedure will get you the results.
Hope this helps.

Categories