Visual Studio database schema compare is very slow - sql-server

We've been using Visual Studio 2017's SQL Server Schema Comparison for all our (SQL Server 2016) migrations and deployments.
However, recently, it has become very slow, taking hours to process. If we uncheck the "Tables" object, it goes quickly. But when tables are checked, it is stuck on "Initializing comparison..." for ages.
I've not been able to find anything online that has helped us. Any ideas?
Initializing comparison...

What seemed to work for us is that if you excluded tables (in Schema Compare Options --> Object types --> Application-scoped -- > Tables), it runs quickly.
After its runs initially, you can compare again with tables selected, and its fine.
With the exception of this, the Visual Studio database Schema Compare is an awesome tool.

You can use MSSQL Server Management Studio's own comparison or use one of these tools:
https://www.agile-code.com/blog/choose-your-sql-server-schema-comparison-tool/

I had very similar problem and I was able to find a solution.
Query starting with SELECT * FROM (SELECT SCHEMA_NAME([o].[schema_id]) AS [SchemaName], from [sys].[spatial_indexes] and other tables had suboptimal plan and was running for hours, causing VS to timeout and retry.
Plan guide included below solved the problem for me.
Because VS sends all queries in one batch during 1st attempt to get results plan guide will not kick in. After query times out, VS will retry this query in its own batch and plan guide will be applied.
To speed up the process even more and don't wait for time out you can kill VS session when it is stuck on this query and force retry.
EXEC sp_create_plan_guide
#name = N'VS Schema Comp Spatial Idxs',
#stmt = N'SELECT * FROM (
SELECT
SCHEMA_NAME([o].[schema_id]) AS [SchemaName],
[si].[object_id] AS [ColumnSourceId],
[o].[name] AS [ColumnSourceName],
[o].[type] AS [ColumnSourceType],
[ic].[column_id] AS [ColumnId],
[c].[name] AS [ColumnName],
[si].[index_id] AS [IndexId],
[si].[name] AS [IndexName],
[ds].[type] AS [DataspaceType],
[ds].[data_space_id] AS [DataspaceId],
[ds].[name] AS [DataspaceName],
[si].[fill_factor] AS [FillFactor],
[si].[is_padded] AS [IsPadded],
[si].[is_disabled] AS [IsDisabled],
[si].[allow_page_locks] AS [DoAllowPageLocks],
[si].[allow_row_locks] AS [DoAllowRowLocks],
[sit].[cells_per_object] AS [CellsPerObject],
[sit].[bounding_box_xmin] AS [XMin],
[sit].[bounding_box_xmax] AS [XMax],
[sit].[bounding_box_ymin] AS [YMin],
[sit].[bounding_box_ymax] AS [YMax],
[sit].[level_1_grid] AS [Level1Grid],
[sit].[level_2_grid] AS [Level2Grid],
[sit].[level_3_grid] AS [Level3Grid],
[sit].[level_4_grid] AS [Level4Grid],
[sit].[tessellation_scheme] AS [TessellationScheme],
[s].[no_recompute] AS [NoRecomputeStatistics],
[p].[data_compression] AS [DataCompressionId],
CONVERT(bit, CASE WHEN [ti].[data_space_id] = [ds].[data_space_id] THEN 1 ELSE 0 END)
AS [EqualsParentDataSpace]
FROM
[sys].[spatial_indexes] AS [si] WITH (NOLOCK)
INNER JOIN [sys].[objects] AS [o] WITH (NOLOCK) ON [si].[object_id] = [o].[object_id]
INNER JOIN [sys].[spatial_index_tessellations] [sit] WITH (NOLOCK) ON [si].[object_id] = [sit].[object_id] AND [si].[index_id] = [sit].[index_id]
INNER JOIN [sys].[data_spaces] AS [ds] WITH (NOLOCK) ON [ds].[data_space_id] = [si].[data_space_id]
INNER JOIN [sys].[index_columns] AS [ic] WITH (NOLOCK) ON [si].[object_id] = [ic].[object_id] AND [si].[index_id] = [ic].[index_id]
INNER JOIN [sys].[columns] AS [c] WITH (NOLOCK) ON [si].[object_id] = [c].[object_id] AND [ic].[column_id] = [c].[column_id]
INNER JOIN [sys].[objects] AS [o2] WITH (NOLOCK) ON [o2].[parent_object_id] = [si].[object_id]
INNER JOIN [sys].[stats] AS [s] WITH (NOLOCK) ON [o2].[object_id] = [s].[object_id] AND [s].[name] = [si].[name]
INNER JOIN [sys].[partitions] AS [p] WITH (NOLOCK) ON [p].[object_id] = [o2].[object_id] AND [p].[partition_number] = 1
LEFT JOIN [sys].[indexes] AS [ti] WITH (NOLOCK) ON [o].[object_id] = [ti].[object_id]
LEFT JOIN [sys].[tables] AS [t] WITH (NOLOCK) ON [t].[object_id] = [si].[object_id]
WHERE [si].[is_hypothetical] = 0
AND [ti].[index_id] < 2
AND OBJECTPROPERTY([o].[object_id], N''IsSystemTable'') = 0
AND ([t].[is_filetable] = 0 OR [t].[is_filetable] IS NULL)
AND ([o].[is_ms_shipped] = 0 AND NOT EXISTS (SELECT *
FROM [sys].[extended_properties]
WHERE [major_id] = [o].[object_id]
AND [minor_id] = 0
AND [class] = 1
AND [name] = N''microsoft_database_tools_support''
))
) AS [_results];
',
#type = N'SQL',
#module_or_batch = NULL,
#params = NULL,
#hints = N'OPTION (FORCE ORDER)';

Related

Custom SQL Query to HTML

I have been doing a lot of research and everything I find is using PHP and MySQL. I need to be able to access my ODBC SQL Server (my MRP system) and display a custom query on a webpage for a visual for my plant. I have not been able to find a way to establish a connection to the database nor the correct way to format the query to display data. Any and all recommendations and formatting corrections are greatly appreciated. I am not even sure HTML is the route I need to go. I just need to build a table based on this data with further ability to format using specific string values from the table.
The query is below:
with cte as
(
SELECT DISTINCT
orout.PartNo,
sched.JobNo,
sched.StepNo,
orout.DeptNum AS MachCell,
orout.WorkCntr as Descrip,
agg.sumHours as HrsLeft,
agg.sumManHrs,
agg.minStartDate,
agg.maxEndDate,
sched.Priority,
od.QtyToMake,
isnull(tt2.QtyComplete,0) as QtyComplete,
CASE
WHEN isnull(tt2.QtyComplete,0) = 0 THEN od.QtyToMake
ELSE (od.QtyToMake - tt2.QtyComplete)
END as QtyOpen,
orout.TotActHrs,
orout.TotEstHrs,
emp.EmplCode,
Emp.NewEmplShortName,
emp.WorkCntr,
wc.Descrip as wcDescrip,
CASE
WHEN emp.EmplCode IS NOT null THEN 1
ELSE 0
END AS LoginPriority
FROM Scheduling as sched
LEFT JOIN OrderRouting as orout
ON orout.JobNo = sched.JobNo AND orout.StepNo = sched.StepNo
LEFT JOIN OrderDet as od
ON orout.JobNo = od.JobNo
LEFT JOIN
(
SELECT
JobNo,
online.EmplCode,
EmplCode.NewEmplShortName,
WorkCntr,
StepNo
FROM Online
INNER JOIN EmplCode
ON EmplCode.EmplCode = online.EmplCode
) emp
ON emp.JobNo = orout.JobNo and emp.StepNo = orout.StepNo
LEFT JOIN
(
SELECT
JobNo,
StepNo,
SUM(ManHrs) as sumManHrs,
SUM(Hours) as sumHours,
MIN(StartDate) as minStartDate,
MAX(EndDate) as maxEndDate
FROM
Scheduling
GROUP BY JobNo, StepNo
) agg
ON agg.JobNo = sched.JobNo AND agg.StepNo = sched.StepNo
LEFT JOIN TimeTicketDet as tt
ON tt.JobNo = orout.JobNo and tt.StepNo = orout.StepNo
LEFT JOIN
(
SELECT
JobNo,
StepNo,
SUM(PiecesFinished+PiecesScrapped) as QtyComplete
FROM
TimeTicketDet as tt2
GROUP BY JobNo, StepNo
) tt2
ON tt2.JobNo = orout.JobNo and tt2.StepNo = tt.StepNo
LEFT JOIN WorkCntr as wc
ON emp.WorkCntr = wc.WorkCntr
WHERE
sched.Priority > 0
)
SELECT *
FROM CTE
WHERE
Descrip = 'MACHINE2'
ORDER BY
LoginPriority DESC, Priority DESC, minStartDate
I would suggest looking for an off-the-shelf application that can use a SQL view as a data source. You can then write a view in SQL to return the data you need displaying, then leave the application to handle everything in the UI.
I've not used any in-depth, and I'm not affiliated with any, but the two I've played with in the past are https://www.tableau.com/ and https://powerbi.microsoft.com. Tableau more of a dashboard tool (and maybe a bit pricey), but I think PowerBI is free, but they're just examples of something you can use. Have a look around, but you should be able to find something that you can use.

VS 2017 Database Project failed to import database to due timed out error

VS 2017 Database Project failed to import database: An error was received from SQL Server while attempting to reverse engineer elements of type Microsoft.Data.Tools.Schema.Sql.SchemaModel.SqlSpatialIndex: Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
I created a SQL Server database project in SSDT 17, Version 15.6.5. I was able to import a few small database. But failed to import our main database which is reasonably large size.
The import failed at Gathering column store indexes with the following errors:
I also checked the SQL Server activity monitor, it was running the query below but it returned nothing when I try to run it manually:
SELECT * FROM (
SELECT
SCHEMA_NAME([o].[schema_id]) AS [SchemaName],
[si].[object_id] AS [ColumnSourceId],
[o].[name] AS [ColumnSourceName],
[o].[type] AS [ColumnSourceType],
[ic].[column_id] AS [ColumnId],
[c].[name] AS [ColumnName],
[si].[index_id] AS [IndexId],
[si].[name] AS [IndexName],
[ds].[type] AS [DataspaceType],
[ds].[data_space_id] AS [DataspaceId],
[ds].[name] AS [DataspaceName],
[si].[fill_factor] AS [FillFactor],
[si].[is_padded] AS [IsPadded],
[si].[is_disabled] AS [IsDisabled],
[si].[allow_page_locks] AS [DoAllowPageLocks],
[si].[allow_row_locks] AS [DoAllowRowLocks],
[sit].[cells_per_object] AS [CellsPerObject],
[sit].[bounding_box_xmin] AS [XMin],
[sit].[bounding_box_xmax] AS [XMax],
[sit].[bounding_box_ymin] AS [YMin],
[sit].[bounding_box_ymax] AS [YMax],
[sit].[level_1_grid] AS [Level1Grid],
[sit].[level_2_grid] AS [Level2Grid],
[sit].[level_3_grid] AS [Level3Grid],
[sit].[level_4_grid] AS [Level4Grid],
[sit].[tessellation_scheme] AS [TessellationScheme],
[s].[no_recompute] AS [NoRecomputeStatistics],
[p].[data_compression] AS [DataCompressionId],
CONVERT(bit, CASE WHEN [ti].[data_space_id] = [ds].[data_space_id] THEN 1 ELSE 0 END)
AS [EqualsParentDataSpace]
FROM
[sys].[spatial_indexes] AS [si] WITH (NOLOCK)
INNER JOIN [sys].[objects] AS [o] WITH (NOLOCK) ON [si].[object_id] = [o].[object_id]
INNER JOIN [sys].[spatial_index_tessellations] [sit] WITH (NOLOCK) ON [si].[object_id] = [sit].[object_id] AND [si].[index_id] = [sit].[index_id]
INNER JOIN [sys].[data_spaces] AS [ds] WITH (NOLOCK) ON [ds].[data_space_id] = [si].[data_space_id]
INNER JOIN [sys].[index_columns] AS [ic] WITH (NOLOCK) ON [si].[object_id] = [ic].[object_id] AND [si].[index_id] = [ic].[index_id]
INNER JOIN [sys].[columns] AS [c] WITH (NOLOCK) ON [si].[object_id] = [c].[object_id] AND [ic].[column_id] = [c].[column_id]
INNER JOIN [sys].[objects] AS [o2] WITH (NOLOCK) ON [o2].[parent_object_id] = [si].[object_id]
INNER JOIN [sys].[stats] AS [s] WITH (NOLOCK) ON [o2].[object_id] = [s].[object_id] AND [s].[name] = [si].[name]
INNER JOIN [sys].[partitions] AS [p] WITH (NOLOCK) ON [p].[object_id] = [o2].[object_id] AND [p].[partition_number] = 1
LEFT JOIN [sys].[indexes] AS [ti] WITH (NOLOCK) ON [o].[object_id] = [ti].[object_id]
LEFT JOIN [sys].[tables] AS [t] WITH (NOLOCK) ON [t].[object_id] = [si].[object_id]
WHERE [si].[is_hypothetical] = 0
AND [ti].[index_id] < 2
AND OBJECTPROPERTY([o].[object_id], N'IsSystemTable') = 0
AND ([t].[is_filetable] = 0 OR [t].[is_filetable] IS NULL)
AND ([o].[is_ms_shipped] = 0 AND NOT EXISTS (SELECT *
FROM [sys].[extended_properties]
WHERE [major_id] = [o].[object_id]
AND [minor_id] = 0
AND [class] = 1
AND [name] = N'microsoft_database_tools_support'
))
) AS [_results]
I have also tried to change to connection timeout setup and no luck.
I had this problem too, even using the regedit settings for QueryCommandTimeout and resolutions to other similar errors. Probably not a "solution" but this is how I was able to work around this problem. I ran the SqlPackage tool from the command line and then imported the resulting DACPAC:
"C:\Program Files (x86)\Microsoft SQL Server\140\DAC\bin\SqlPackage.exe" /Action:Extract /SourceConnectionString:"Data Source=localhost;Initial Catalog=MyDB;Integrated Security=True;" /TargetFile:"path\to\database.dacpac" /p:CommandTimeout="0"
Note the /p:CommandTimeout="0". You may want to try large values for that before going to 0.

Optimizing SQL query with multiple joins and conditions

I'm trying to figure out a way to optimize my query as it is taking more than 48 hrs to execute the script as I have a huge database. I tried creating all possible indexes in the required tables. I even tried to break the query into sub queries but still no luck with the improve in execution time. Any comments or ideas are appreciated. Here is my query :
SELECT distinct
etb.ID_Etab AS Siret
,ctt.DebutCTT AS DateMouvement
,ctt.L_Contrat_SQN
,ctt.Numero
,ctt.DebutCTT
,ctt_pcs.PcsEse
,ctt.DerDSN
,ctt.H_Etab_SQN
,ctt.H_Salarie_SQN
,ISNULL(ctt_nat.Nature, '') AS Nature,
ctt_dpp.DispPolitiquePublique,
ctt_det_exp.DetacheExpatrie,
ctt_SS.StatutSalarie,
ctt_stat.CodeStatutEmploi,SSS.Num_Inscr AS NIR_RECODE
FROM [dbo].[Lnk_Contrat] AS ctt
INNER JOIN [dbo].[LSat_Contrat_Etab] AS ctt_etb ON ctt.L_Contrat_SQN = ctt_etb.L_Contrat_SQN
INNER JOIN [dbo].[Hub_Etab] AS etb ON ctt_etb.Siret = etb.ID_Etab
INNER JOIN [dbo].[LSat_Contrat_PcsEse] AS ctt_pcs ON ctt.L_Contrat_SQN = ctt_pcs.L_Contrat_SQN and ctt.DebutCTT BETWEEN ctt_pcs.Debut AND ctt_pcs.Fin
INNER JOIN [dbo].[LSat_Contrat_Nature] AS ctt_nat ON ctt.L_Contrat_SQN = ctt_nat.L_Contrat_SQN AND ctt.DebutCTT BETWEEN ctt_nat.Debut AND ctt_nat.Fin AND ISNULL(ctt_nat.Nature, '') <>03
LEFT join Sat_Salarie_SNGI SSS ON SSS.H_Salarie_SQN=ctt.H_Salarie_SQN AND ctt.DebutCTT BETWEEN SSS.Debut AND SSS.Fin
Left JOIN dbo.LSat_Contrat_DispPoliPub AS ctt_dpp ON ctt_dpp.L_Contrat_SQN = ctt.L_Contrat_SQN
INNER JOIN dbo.LSat_Contrat_DetacheExpatrie AS ctt_det_exp ON ctt_det_exp.L_Contrat_SQN = ctt.L_Contrat_SQN AND ctt.DebutCTT BETWEEN ctt_det_exp.Debut AND ctt_det_exp.Fin
INNER JOIN dbo.LSat_Contrat_StatutSalarie AS ctt_SS ON ctt_SS.L_Contrat_SQN = ctt.L_Contrat_SQN AND ctt.DebutCTT BETWEEN ctt_SS.Debut AND ctt_SS.Fin
LEFT JOIN dbo.LSat_Contrat_StatutEmploiSalarie AS ctt_stat ON ctt_stat.L_Contrat_SQN = ctt.L_Contrat_SQN AND ctt.DebutCTT BETWEEN ctt_stat.Debut AND ctt_stat.Fin
WHERE
ctt.Creation_DTS > '1900-01-01'
AND ctt_etb.Debut = '1900-01-01'
AND ctt_etb.[Type] = 'AF'
AND ctt.DebutCTT >= ctt_etb.Debut
AND ctt.DebutCTT >= etb.PreDSN
AND ctt.debutCTT>=DATEADD(MONTH, -1, ctt.PreDSN)
AND ((ctt.DebutCTT BETWEEN ctt_dpp.Debut AND ctt_dpp.Fin) or ctt_dpp.Fin is null)
order by Siret,L_Contrat_SQN
DBCC TRACEOFF (610)
Into the Sql Server Management Studio paste the SQL sentence and click on "Display Estimated Execution Plan". It shows how Sql Server will try to execute your sentence analyzing exiting indexes of your Where(s) and Join(s).
Also try to upgrade your hardware, so each Sql sentence may required a huge ammount of memory and cpu cycles depending of the number of records.

How to increase performance of this query?

I have an SQL query, it is running on MSSQL 2008 R2
View vMobileLastMobileHistory has about 1000 rows and
select * from vMobileLastMobileHistory is taking 0.2 sec
but this query is taking 5 seconds, how can I optimize this code?
(I think the problem is INTERSECT but I dont know how change this)
SELECT DISTINCT *
FROM
(
SELECT vMobileLastMobileHistory.*
FROM vMobileLastMobileHistory
LEFT OUTER JOIN MobileType_DomainAction ON
MobileType_DomainAction.tiMobileType = vMobileLastMobileHistory.tiMobileType
LEFT OUTER JOIN MobileType_User ON
MobileType_User.MobileID = MobileType_DomainAction.ID
WHERE MobileType_User.UserID = #UserID OR #UserID = - 1
INTERSECT
SELECT vMobileLastMobileHistory.*
FROM vMobileLastMobileHistory
LEFT OUTER JOIN dbo.Region_User ON
dbo.vMobileLastMobileHistory.strRegion = dbo.Region_User.strRegion
WHERE Region_User.iSystemUser = #UserID OR #UserID = - 1
INTERSECT
SELECT vMobileLastMobileHistory.*
FROM vMobileLastMobileHistory
LEFT OUTER JOIN Contractor_User ON
vMobileLastMobileHistory.strContractor = Contractor_User.strContractor
WHERE Contractor_User.iSystemUser = #UserID OR #UserID = - 1
)
The problem is that if you have any indexes on your iSytemUser columns, the optimise is unable to use them because it has to account for a specific userID being passed, or returning all results, it would be better to logically separate your two cases. In addition, since you don't care about any columns in the auxiliary tables, you could use EXISTS in your case of specific users to take advantage of a semi join:
IF (#UserID = -1)
BEGIN
SELECT DISTINCT *
FROM vMobileLastMobileHistory;
END
ELSE
BEGIN
SELECT DISTINCT *
FROM vMobileLastMobileHistory AS mh
WHERE EXISTS
( SELECT 1
FROM Contractor_User AS cu
WHERE cu.strContractor = mh.strContractor
AND cu.iSystemUser = #UserID
)
AND EXISTS
( SELECT 1
FROM Region_User AS ru
WHERE ru.strRegion = mh.strRegion
AND ru.iSystemUser = #UserID
)
AND EXISTS
( SELECT 1
FROM MobileType_DomainAction AS da
INNER JOIN MobileType_User AS mu
ON mu.MobileID = da.ID
WHERE da.tiMobileType = mh.tiMobileType
AND mu.iSystemUser = #UserID
);
END
Now you can have two execution plans for each case (returning all results, or for a specific user), in each case you only need to read from vMobileLastMobileHistory once, and you also limit the sorts required by removing the INTERSECT and replacing with 3 EXISTS clauses.
If they don't already exist then you may also which to consider some indexes on your tables. A good way of finding out what indexes would help is to run the query in SQL Server Management Studio with the option "Show Actual Execution Plan" enabled, this will then show you any missing indexes.
Most of time Intersect and Inner Join will be same. You are not share your data, so based on my knowledge and this link, I just replace intersect query into Inner join query as :
--I think you don't need distinct upper query. If you have issue inform me.
SELECT DISTINCT vml.*
FROM vMobileLastMobileHistory vml
LEFT OUTER JOIN MobileType_DomainAction mtda ON mtda.tiMobileType = vml.tiMobileType
LEFT OUTER JOIN MobileType_User ON MobileType_User.MobileID = mtda.ID
LEFT OUTER JOIN dbo.Region_User ON dbo.vml.strRegion = dbo.Region_User.strRegion
LEFT OUTER JOIN Contractor_User ON vml.strContractor = Contractor_User.strContractor
WHERE
(MobileType_User.UserID = #UserID
and Region_User.iSystemUser = #UserID or Contractor_User.iSystemUser = #UserID
) OR #UserID = - 1

Optimize Entity Framework Generated SQL Server Execution Plan

I have a data structure that is basically a document with a dictionary of tags. I am attempting to bring back all documents of a given formtype that have a tag named 'Last Name' and a tag value of 'Smith'. There may be 0..N 'Last Name' tags associated with the document.
I am using the following linq query to try to match a source document to children with matching tags:
DB.Documents
.Where(doc => doc.FormID == pd.IndexForm.FormID)
.Where(doc => doc.Document_StringIndex_ReadOnly
.Join(Fields,
dsi => new { FieldName = dsi.FieldName, FieldValue = dsi.StringValue },
dsi2 => new { FieldName = dsi2.FieldName, FieldValue = dsi2.StringValue },
(dsi, dsi2) => dsi.Document).Count() > 0);
Which generates the following query when output using .ToTraceString()
SELECT
[Project1].*
FROM ( SELECT
[Extent1].*
(SELECT
COUNT(cast(1 as bit)) AS [A1]
FROM [dbo].[Document_StringIndex_ReadOnly] AS [Extent2]
INNER JOIN (SELECT [Extent3].*
FROM [dbo].[Document] AS [Extent3]
INNER JOIN [dbo].[Document_StringIndex_ReadOnly] AS [Extent4] ON [Extent3].[DocumentID] = [Extent4].[DocumentID] ) AS [Join1] ON (([Extent2].[FieldName] = [Join1].[FieldName]) OR (([Extent2].[FieldName] IS NULL) AND ([Join1].[FieldName] IS NULL))) AND (([Extent2].[StringValue] = [Join1].[StringValue]) OR (([Extent2].[StringValue] IS NULL) AND ([Join1].[StringValue] IS NULL)))
LEFT OUTER JOIN [dbo].[Document] AS [Extent5] ON [Extent2].[DocumentID] = [Extent5].[DocumentID]
WHERE ([Extent1].[DocumentID] = [Extent2].[DocumentID]) AND ([Join1].[DocumentID1] = #p__linq__7) AND ([Join1].[FieldName] = #p__linq__8)) AS [C1]
FROM [dbo].[Document] AS [Extent1]
WHERE [Extent1].[FormID] = #p__linq__5
) AS [Project1]
WHERE [Project1].[C1] > 0
If I do a direct substitution of constants for my parameters (as shown below) the query executes very quickly. However, if I leave the parameters in place the query takes several minutes.
SELECT
[Project1].*
FROM ( SELECT
[Extent1].*
(SELECT
COUNT(cast(1 as bit)) AS [A1]
FROM [dbo].[Document_StringIndex_ReadOnly] AS [Extent2]
INNER JOIN (SELECT [Extent3].*
FROM [dbo].[Document] AS [Extent3]
INNER JOIN [dbo].[Document_StringIndex_ReadOnly] AS [Extent4] ON [Extent3].[DocumentID] = [Extent4].[DocumentID] ) AS [Join1] ON (([Extent2].[FieldName] = [Join1].[FieldName]) OR (([Extent2].[FieldName] IS NULL) AND ([Join1].[FieldName] IS NULL))) AND (([Extent2].[StringValue] = [Join1].[StringValue]) OR (([Extent2].[StringValue] IS NULL) AND ([Join1].[StringValue] IS NULL)))
LEFT OUTER JOIN [dbo].[Document] AS [Extent5] ON [Extent2].[DocumentID] = [Extent5].[DocumentID]
WHERE ([Extent1].[DocumentID] = [Extent2].[DocumentID]) AND ([Join1].[DocumentID1] = 1015) AND ([Join1].[FieldName] = 'DDKey')) AS [C1]
FROM [dbo].[Document] AS [Extent1]
WHERE [Extent1].[FormID] = 22
) AS [Project1]
WHERE [Project1].[C1] > 0
After generating an execution plan, I learned that if I directly substitute the parameter values, SQL Server performs an index seek, and my query is fast. As soon as I leave the parameters in place, SQL Server will perform an index scan, and my query times out. Is there any way to prod SQL server to always seek? Can I force entity framework to not use parameterized queries?
In the generated SQL, this line
[Join1].[FieldName] = #p__linq__8
may be the problem.
If FieldName is varchar(...) and #p__linq__8 is nvarchar(...) then this clause will cause a table scan since the parameter type doesn't match the index type.
When you directly substitute 'DDKey' then the types match so you get an index seek. Try your query with N'DDkey' and see if you get a table scan.
This is an issue with various versions of Linq to Sql and Linq to Entities, but may be fixed in later releases.
One way to work around the problem if you can't update to the latest version would be to change FieldName to be nvarchar(...).

Resources