tags:

views:

54

answers:

5

Hello, I wrote this LINQ code:

from workTask in VwWorkTask.Where(e => e.TaskStateStr != "A" 
                                    && e.TaskStateStr != "B")
join workContext in TblWorkTOBProlongationWorkContexts 
        on workTask.WorkContextId equals workContext.Id  
join client in VwClient 
        on workContext.Client equals client.ClientId  into t1
from client in t1.DefaultIfEmpty()
....// other joins
select workTask

Which generates this T-SQL query:

SELECT [t0].*
FROM [vwWorkTask] AS [t0]
INNER JOIN [tblWorkTOBProlongationWorkContext] AS [t1] 
        ON [t0].[WorkContextId] = ([t1].[Id])
LEFT OUTER JOIN [vwClient] AS [t2] ON [t1].[Client] = [t2].[ClientId]
... -- other joins
WHERE ([t0].[TaskStateStr] <> @p0) AND ([t0].[TaskStateStr] <> @p1)

But I`m need something like that instead:

SELECT [t0].*
FROM [select * vwWorkTask WHERE ([t0].[TaskStateStr] <> @p0) 
                          AND ([t0].[TaskStateStr] <> @p1)] AS [t0]
INNER JOIN [tblWorkTOBProlongationWorkContext] AS [t1] 
        ON [t0].[WorkContextId] = ([t1].[Id])
LEFT OUTER JOIN [vwClient] AS [t2] ON [t1].[Client] = [t2].[ClientId]
... -- other joins

In other words I need nested query with "where" check before all joins, not after. Any ideas how can I rewrite LINQ query to accomplish that?

Thanks.

A: 

Are you sure you need that?

The two query should be effectively the same.

I think you are worried that the data server is doing more work than needed, but you should trust that it knows what it is doing.

James Curran
Yep, I pretty sure. Even after filtration there are thousands rows from VwWorkTask view. I think It`s bad idea get all to BL level. Ok, imagine I do that, but what next? Write another linq query which translates in t-sql with "where Table.LinkToTaskId in (...list of thousand previously fetched ids...)" in the end?
Vlad
>you should trust that it knows what it is doingGenerated t-sql query executes about 18 secs, which completly inappropriate. Second one, written "by hands", executes 2 secs at max.
Vlad
A: 

Ok, maybe there are another options? Maybe I must try to convince my co-workers and PM that LINQ2SQL and, maybe ORMs at all, - bad choose for our project and we must rewrite queries using only sql, before it`s too late?

Vlad
A: 

Generated t-sql query executes about 18 secs, which completly inappropriate. Second one, written "by hands", executes 2 secs at max.

Show us the actual queries and we'll show you where the filtering occurs in the second one that allows it to use indexing.

Until then, you're just trolling.

David B
Original post contains both queries. What else do your need? They almost identical except one little detail - generated query apply "where" conditions after all joinings. I believe that MSSQL optimizer cant built optimal execution plan because of nested views.
Vlad
Original post contains sql fragments, not queries. Second fragment has a syntax error. Your belief is wrong - nested views present no challenge to the optimizer.
David B
A: 

Show us the actual queries

Original post contains both queries. What else do your need? They almost identical except one little detail - generated query apply "where" conditions after all joinings. I believe that MSSQL optimizer cant built optimal execution plan because of nested views... But in the other hand I cant just stop using this views, otherwise man responsible for their creation just would kill me.

A: 

If you aren't satisfied with the TSQL that's being generated, then consider your option of writing your exact query into a stored procedure. Make a new stored procedure, perhaps named GetWorkTaskClientSomething. Paste that TSQL call with the appropriate parameters required.

You can then map the return result sets to a custom class of your choice. You can write this from scratch, or reuse an existing class.

That would allow you to control the TSQL as you see fit, and would allow you to continue using the model classes that LINQ To SQL providers for you.

List<foo> = db.GetWorkTaskClientSomething('foo', 'bar', 1);
p.campbell
Thanks for reply.Regretfully I cannot wrap entire query in SP or function, because there are actually a lot of cases, so conditions for "where" clause cannot be generalized and sended into stored procedure as parameters. It can be for example (State = 'created' and ClientId = 'GUID-HERE') in one case and (State <> 'cancelled' or State <> 'ended' and TaskType = 'GUID-TYPE') in another. It will be very disappointing if I need to create a procedure for each unique variation of the parameters. Now my only option - dynamically create query in C# code and use db.ExecuteQuery<Type>("...").
Vlad