In the Linq2Sql query below could someone tell me
1) When is the sql query sent to sql server?
a) When query has the expression assigned to it or
b) (deferred execution) when it is required in the foreach loop?
var query = from c in myDataContext.Customers
where c.FirstName == 'Tom'
select c;
foreach(customer cust in query)
{
//...do something
}
2) Does the .NET application or SQL Server convert the expression tree into a SQL query? The reason I ask this is because
a) All the reading I've done on expression trees says that they were needed in order to send code across the wire to be executed dynamically instead of sending MSIL.
b) If I hover over query after the expression is assigned to it, I can already see it has changed it to SQL
If the .NET application does the conversion then how can it really be said that an expression tree was sent over the wire to sql server? It just sent the sql string.
The query is sent to the database whenever it absolutely has to be - usually when you start actually requesting data.
In other words, it'll probably be either the call to GetEnumerator() or the first call to IEnumerator<T>.MoveNext().
The C# compiler converts the lambda expression into IL which produces the expression tree object at execution time. LINQ to SQL then converts that expression tree to SQL to send to the database.
Expression trees are needed for LINQ to SQL in order to have a "data" representation of your code so that it can be converted to SQL at execution time. It's still SQL which is sent over the wire, but expression trees are required to create that SQL.
There are lots of blog posts on this sort of thing, including this one by me a while ago.
Related
I have a Linq query done in LINQPad. This query has some froms, joins and a where clause (neither group by nor order by are used).
In where clause I am using below function to remove time from a DateTime field:
System.Data.Entity.DbFunctions.TruncateTime(myField)
This query return the results into a:
IQueryable<MyCustomClass>
When I execute query from LINQPad it is executed correctly without errors, but If I perform results.Dump() or results.ToList().Dump() in order to view the results in LINQPad I get below error:
TruncateTime(System.Nullable`1[System.DateTime])' has no supported
translation to SQL.'
This is not LinqPad specific.
This basically means that the Where clause contains some conditions that can not be successfully translated from Linq to SQL.
In order to get around this you can split the where clause:
First part of the where clause contains all the SQL compatible operations, then add a .ToList() which will retrieve the data from the database, then finish with the non-SQL, but Linq to Object compatible part of the where clause.
I realize this will cause a greater pull from the database, but that is the limitation.
I am working with MVC Core with EF-6.x and I am using Lambda expression, but my senior told me use LINQ why, because while using lambda with where clause it will pull all the data from database and later it will apply where condition. In case of LINQ if you use where condition it will pull only filtered data. Please let me know what is correct?
e.gLambda: context.tablename.where(condition);// Should I go with this
LINQ: (from T in tablename where t.(condition));// or this?
Please let me know what is correct?
e.gLambda: context.tablename.where(condition);// Should I go with this
LINQ: (from T in tablename where t.(condition));// or this?
Short answer: it doesn't really matter. Since context.tablename ultimately returns an IQueryable<T>, Entityframework will not try to hit the database until you try to iterate the final result from your expression, not to mention, .ToArray() and .ToList() each, does that iteration for you.
Either you used LINQ expression syntax (which gets compiled as LINQ methods) or LINQ methods, when you attempt to begin iterating the results, Entityframework creates an Expression tree for you underneath the hood that consists of your query altogether (including Wheres, Joins, GroupBys, etc). Since the structure of a LINQ might not percisely match the structure of a SQL query (or whatever data-source query), depending on the source (i.e database, e.g SQL Server), Entityframework then attempts to make the best possible optimization to your expression tree so that its structure would match an executable query on the source (e.g SQL Server query). Finally, it translates that expression tree into an actual query and executes it against the data source, and return your data (after doing all the mapping of course).
If you really, and I mean REALLY want to go through the complications of how an IQueryable engine works, I'd suggest taking a walk through Matt Warren's series: 'LINQ: Building an IQueryable provider series'. That's not actually Entityframework but it shares the same concept.
Both syntax will be translated into the same IL code. The difference, if the filter will be applied on server or client side is, if the source is IQueryable<T> or IEnumerable<T>.
my senior told me use LINQ why, because while using lambda with where
clause it will pull all the data from database and later it will apply
where condition.
Your senior is wrong, you can use the statement you prefer they are the same, both will filter the data at database level. If you have Sql Server as database server, you can use Sql Server Profiler to dump the queries executed by both statements and you will see that they are the same.
I have the following code that takes 5-8 seconds to complete:
recent_items returnedData = (from d in db.recent_items
where d.item_number == scannerInput.Text.ToUpper()
select d).FirstOrDefault();
Where as the following executes in less than a half second:
string search = scannerInput.Text.ToUpper();
recent_items returnedData = (from d in db.recent_items
where d.item_number == search
select d).FirstOrDefault();
What in the world is going on?
The most likely reason for the discrepancy is that EF evaluates the first condition in memory, after retrieving all rows from RDBMS.
Microsoft documentation says the following about Client vs. Server Evaluation:
Entity Framework Core supports parts of the query being evaluated on the client and parts of it being pushed to the database. It is up to the database provider to determine which parts of the query will be evaluated in the database.
Your EF DB provider could not send scannerInput.Text.ToUpper() to RDBMS for evaluation, so it did all comparisons in memory, after retrieving data rows from the database. This decision is correct, because EF DB provider cannot assume that consecutive evaluations of the above expression would yield identical results.
Second query, on the other hand, used a captured variable for the query. The value of that variable is guaranteed to stay constant while EF runs the query, so it proceeded to evaluating the request on the RDBMS side.
I need a Linq with distinct operation in C# app
SQL should be :
select distinct(col1) from tableName;
I read some e.gs and know that i can write Linq like:
var myRes =
(
from a in tableName
select a.col1
).Distinct();
So here is my question:
Does this linq :
get a whole set of col1 from the MSSQL server to the myRes,
then use C# distinct() function to make distinct at my app side?
if it does so ,
can i make it distincted at the server side?
Or it does:
only get the distincted col1 from the MSSQL server,
and nothing to do at my app side?
Thanks a lot!
This should be performing the DISTINCT filter at the database side, unless something else is making the query execute before the filter is applied. You can confirm this by running SQL Server Profiler when the query executes.
The way this works is by using deferred execution. That is, the query doesn't actually run against the database until it needs to. Prior to that, it builds up what's called an expression tree which then gets evaluated against the data source. So you can append more and more IQueryable<T> extension methods on that statement, and they should all translate into a single query against the database.
What you're passing around in this case (myRes) isn't really the result set, it's a reference to the query which will create the result set. The query gets built and evaluated when the enumeration is evaluated into an actual result set. Such as when you call:
.ToList()
.Single()
.SingleOrDefault()
.First()
.FirstOrDefault()
etc.
Basically anything that takes a reference to a query and turns it into an actual value or collection of values.
Is it possible to use custom method In query for example:
var result = from u in context.MyTable where MyMethod(u) == 10 select u;
As Pranay explains, you cannot have a custom (C#) method as part of the LINQ to SQL query, because LINQ to SQL wouldn't be able to look at the expression tree of the method and so it cannot translate it to SQL.
One option that you have is to write your function in SQL and store it as a SQL function on the SQL Server (possibly, you could also use SQL CLR, but I have not tried that). Then you can add the function to your DataContext type and LINQ to SQL will translate it to calls to the function on SQL server. Something like:
var result = from u in context.MyTable
where context.MyMethod(u) == 10 select u;
The problem, of course, is that you'll need to write the function in SQL (I think SQL CLR could also work - not sure about the performance and other possible complications though)
I also wrote an article (some time ago) that shows how to do this when you write the "method" as an expression tree way (as a value of type Expression<Func<...>>), which is possible, because in this case, the code is compiled as an expression tree. However, there is some postprocessing that has to be done and you can still write just a single expression that can be easily inlined in the LINQ query.
Check this full article : What is and what isn't possible with linq
Following is not possible
// function used in filter
static bool MyFunc(Nwind.Product p)
{
return p.ProductName.StartsWith("B");
}
// query that uses MyFunc
var q =
from p in db.Products
where MyPriceFunc(p.UnitPrice) > 30m
select p
It compiles with no errors, but when you execute it LINQ to SQL throws an exception saying: "Static method System.Boolean MyTest(LINQTest.Nwind.Product) has no supported translation to SQL."
The exception is actually thrown when you try to fetch results from q (for example using the foreach statement), because LINQ to SQL attempts to convert the expression trees to T-SQL only when the results are needed and the query must be executed.
To fix the example you can simply copy the code that checks whether product name starts with "B" to the where clause of the query and it would work fine.
Yes, but if you are using Linq-to-Sql - your method has to have special code to handle to SQL conversion.