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

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

Related

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

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.

How to write Nested LINQ for specific scenario

Apologized to post a problem for which i could not construct anything solid. it is very shameful for me to post like this kind of question even after having so high reputation for this web site.
Most of the time i write sql in store procedure in sql server and hardly use LINQ. so facing problem to construct a nested LINQ query for a specific scenario. just wonder if anyone could help me or give me hints to construct such query with linq.
here i am providing a sample sql query which i want to construct the same one with LINQ.
SELECT EmployeeName,
(Select count(*) from table1 where condition) as data1,
(Select count(*) from table1 where condition) as data2,
(Select count(*) from table1 where condition) as data3
though i have seen couple of nested linq sample from these urls but still could not figure out how to construct mine.
http://odetocode.com/blogs/scott/archive/2007/09/24/nested-selects-in-linq-to-sql.aspx
https://social.msdn.microsoft.com/Forums/en-US/00340c95-221a-4b16-9c47-d1acbf2415dc/linq-nested-select-issue?forum=linqtosql
http://www.mercurynewmedia.com/blog/blog-detail/mercury-new-media-blog/2014/05/19/linq-join-queries-vs-nested-sub-queries
http://www.codethinked.com/the-linq-selectmany-operator
Nested Select linq query
http://www.java2s.com/Code/CSharp/LINQ/Nestedquerylist.htm
so just wonder if anyone could help.
This is a good example of something to do in Linq. You will find that you can do this easily and even more powerful queries if you understand two things:
Don't try to overly literally translate from SQL into Linq.
Lambdas.
The first is easy to understand but hard to carry out. Some of the Linq keywords are intentionally like SQL keywords. Linq tries to mirror some aspects of SQL without working in exactly the same way. One key difference is that with Linq, each function yields (no pun intended) a Linq object which can be passed to another Linq function. Thus filtering, transforming, aggregating, etc. can be done repeatedly in the order the programmer chooses. In SQL a single query is built up of several elements such as WHERE, FROM, some of which are optional, and the SQL engine decides in which order to evaluate them.
Get LinqPad and use it for playing with queries, and for doing database queries instead of writing SQL code in SSMS. When you have seen and written enough Linq constructs, you will no longer be writing transliterated SQL, and you will be able to switch back and forth between the two.
Secondly, make sure you understand lambdas. What does
x => x + 23
mean? What is its type? What is the type of its argument and return value? What about
(x, y) => x + y * 23
and
() => "Fish"
?
Select in Linq takes as argument a function. What Select does is the simplest possible thing to understand - it takes an iterator of input objects and a function, and returns an iterator of output objects, which are the input objects having had the function applied to them. This is actually easier to understand with a lambda than with a named function.
Remember that everything in C# has a type. A lambda has a type, even if the type is not explicit. Error messages usually tell you exactly what is wrong, except that sometimes they can be misinterpreted and seem to be pointing to exactly the wrong piece of code, and this can be very time-consuming to figure out. Break down the code you are writing into as small pieces as possible, and debug them in Linqpad.
You can get a long way with this. Try looking at a suggestion for a similar query to yours below and see if you can build on it.
/* A very simple dataset */
string s = "THE QUICK BROWN FOX JUMPED OVER THE LAZY DOG";
var x = s.Split();
/* The letters list plays the role of your EmployeeName */
var letters = new List<String>{"A", "E", "I", "O", "U"};
var result = letters
.Select(letter => new {letter = letter,
startswith = x.Count(w => w.StartsWith(letter)),
contains = x.Count(w => w.Contains(letter)),
endswith = x.Count(w => w.EndsWith(letter))});
If you get this far, you might want to learn more about how the Linq functions operate on iterators. Check out Jon Skeet's Edulinq series of blog posts: http://codeblog.jonskeet.uk/2011/02/23/reimplementing-linq-to-objects-part-45-conclusion-and-list-of-posts/ He reimplements Linq to show how it might be designed and how it should work.
Linqpad and Edulinq and two of the best programming resources I know of, in any language, and I recommend them in almost every Linq question I answer. Check them out.

EF LINQ ToList is very slow

I am using ASP NET MVC 4.5 and EF6, code first migrations.
I have this code, which takes about 6 seconds.
var filtered = _repository.Requests.Where(r => some conditions); // this is fast, conditions match only 8 items
var list = filtered.ToList(); // this takes 6 seconds, has 8 items inside
I thought that this is because of relations, it must build them inside memory, but that is not the case, because even when I return 0 fields, it is still as slow.
var filtered = _repository.Requests.Where(r => some conditions).Select(e => new {}); // this is fast, conditions match only 8 items
var list = filtered.ToList(); // this takes still around 5-6 seconds, has 8 items inside
Now the Requests table is quite complex, lots of relations and has ~16k items. On the other hand, the filtered list should only contain proxies to 8 items.
Why is ToList() method so slow? I actually think the problem is not in ToList() method, but probably EF issue, or bad design problem.
Anyone has had experience with anything like this?
EDIT:
These are the conditions:
_repository.Requests.Where(r => ids.Any(a => a == r.Student.Id) && r.StartDate <= cycle.EndDate && r.EndDate >= cycle.StartDate)
So basically, I can checking if Student id is in my id list and checking if dates match.
Your filtered variable contains a query which is a question, and it doesn't contain the answer. If you request the answer by calling .ToList(), that is when the query is executed. And that is the reason why it is slow, because only when you call .ToList() is the query executed by your database.
It is called Deferred execution. A google might give you some more information about it.
If you show some of your conditions, we might be able to say why it is slow.
In addition to Maarten's answer I think the problem is about two different situation
some condition is complex and results in complex and heavy joins or query in your database
some condition is filtering on a column which does not have an index and this cause the full table scan and make your query slow.
I suggest start monitoring the query generated by Entity Framework, it's very simple, you just need to set Log function of your context and see the results,
using (var context = new MyContext())
{
context.Database.Log = Console.Write;
// Your code here...
}
if you see something strange in generated query try to make it better by breaking it in parts, some times Entity Framework generated queries are not so good.
if the query is okay then the problem lies in your database (assuming no network problem).
run your query with an SQL profiler and check what's wrong.
UPDATE
I suggest you to:
add index for StartDate and EndDate Column in your table (one for each, not one for both)
ToList executes the query against DB, while first line is not.
Can you show some conditions code here?
To increase the performance you need to optimize query/create indexes on the DB tables.
Your first line of code only returns an IQueryable. This is a representation of a query that you want to run not the result of the query. The query itself is only runs on the databse when you call .ToList() on your IQueryable, because its the first point that you have actually asked for data.
Your adjustment to add the .Select only adds to the existing IQueryable query definition. It doesnt change what conditions have to execute. You have essentially changed the following, where you get back 8 records:
select * from Requests where [some conditions];
to something like:
select '' from Requests where [some conditions];
You will still have to perform the full query with the conditions giving you 8 records, but for each one, you only asked for an empty string, so you get back 8 empty strings.
The long and the short of this is that any performance problem you are having is coming from your "some conditions". Without seeing them, its is difficult to know. But I have seen people in the past add .Where clauses inside a loop, before calling .ToList() and inadvertently creating a massively complicated query.
Jaanus. The most likely reason of this issue is complecity of generated SQL query by entity framework. I guess that your filter condition contains some check of other tables.
Try to check generated query by "SQL Server Profiler". And then copy this query to "Management Studio" and check "Estimated execution plan". As a rule "Management Studio" generatd index recomendation for your query try to follow these recomendations.

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.

linq to dataset equivalent of SQL LIKE clause

What is the linq equivalent of a SQL clause like WHERE UserName LIKE 'fr_d'?
I'm working with a dataset in memory rather than a SQL database so I don't think I can use something like where SqlMethods.Like(p.UserName, "Fr_d")
(Not that my installation of VS2008 is admitting that SqlMethods or even System.Data.Linq.SqlClient
exist at the moment, but thats a whole different problem!)
Like this:
table.Where(row => row.StringColumn.StartsWith("prefix"))
(You may also want to call Contains or EndsWith)
EDIT: In your case, you want
table.Where(p => p.UserName.StartsWith("Fr") && p.UserName.EndsWith("d") && p.UserName.Length == 4)
Alternatively, you can also put a regex inside the Where clause.
If you do, make sure to create the RegEx object outside the Where call so that it doesn't get parsed for each row.
I belive this is what you really want. It will allow Fr{any one character}d:
table.Where(p => p.UserName.StartsWith("Fr") && p.UserName.EndsWith("d") && p.UserName.Length == 4 )
Unfortunately I can't find anything that does something similar to SQL's like clause for LINQ to Dataset...
UPDATE: Found a similar posting here: LINQ vs. DataTable.Select - How can I get the same results?
They suggest using i4o which I am not familiar with, but it may be worth investigating (the asker of that question accepted i4o as the answer).

Categories