Retrieving data from TestStand generated SQL database using EF - extremely slow - c#

We have a new production line in our factory which has a bunch of testers on. These testers are running LabView and are logging their data to an SQL database, which was generated by TestStand.
I have written a program in c# and using Entity FrameWork 6 to retrieve data based on a couple of filters i.e. date and tester number.
I am finding that querys that require retrieving data from multiple tables are running very very slow.
Here is an example of a query
using (var db = new LoggingEntities())
{
db.Configuration.AutoDetectChangesEnabled = false;
db.Configuration.LazyLoadingEnabled = false;
db.Configuration.ProxyCreationEnabled = false;
db.Database.CommandTimeout = 5000;
var Results = db.UUT_RESULT.Include("STEP_RESULT")
.Include("STEP_RESULT.STEP_NUMERICLIMIT1") .Include("STEP_RESULT.STEP_NUMERICLIMIT1.STEP_NUMERICLIMIT2")
.Include("STEP_RESULT.PROP_RESULT")
.AsNoTracking()
.Where(x => x.STATION_ID == SelectedTester && x.START_DATE_TIME.Value >= StartFilterDate && x.START_DATE_TIME.Value <= endDate).ToList();
}
At the time of writing this, the above query has been running for 40 minutes. I estimate that in total, across all 5 tables, this is retrieving 336,000 rows.
If I run the above without the includes, the query is completed in a few seconds with 500 Rows retrieved.
Just some extra info.
SQL is running on SQLEXPRESS - Yes i know this is not great and we are planning to move this onto our SQL server.
All Primary keys in the tables are GUID data type and so are the Relational Columns.
So based on the above, is this expected? especially with SQLEXPRESS? or does anyone suspect something else is wrong?
Based on what I have to work wit, is there a better was to do this, performance wise?
EDIT: SQL Profiler Trace
exec sp_executesql N'SELECT
[Project4].[C1] AS [C1],
[Project4].[ID] AS [ID],
[Project4].[STATION_ID] AS [STATION_ID],
[Project4].[BATCH_SERIAL_NUMBER] AS [BATCH_SERIAL_NUMBER],
[Project4].[TEST_SOCKET_INDEX] AS [TEST_SOCKET_INDEX],
[Project4].[UUT_SERIAL_NUMBER] AS [UUT_SERIAL_NUMBER],
[Project4].[USER_LOGIN_NAME] AS [USER_LOGIN_NAME],
[Project4].[START_DATE_TIME] AS [START_DATE_TIME],
[Project4].[EXECUTION_TIME] AS [EXECUTION_TIME],
[Project4].[UUT_STATUS] AS [UUT_STATUS],
[Project4].[UUT_ERROR_CODE] AS [UUT_ERROR_CODE],
[Project4].[UUT_ERROR_MESSAGE] AS [UUT_ERROR_MESSAGE],
[Project4].[PART_NUMBER] AS [PART_NUMBER],
[Project4].[TSR_FILE_NAME] AS [TSR_FILE_NAME],
[Project4].[TSR_FILE_ID] AS [TSR_FILE_ID],
[Project4].[TSR_FILE_CLOSED] AS [TSR_FILE_CLOSED],
[Project4].[StationType] AS [StationType],
[Project4].[C57] AS [C2],
[Project4].[C3] AS [C3],
[Project4].[C4] AS [C4],
[Project4].[C5] AS [C5],
[Project4].[C6] AS [C6],
[Project4].[C7] AS [C7],
[Project4].[C8] AS [C8],
[Project4].[C9] AS [C9],
[Project4].[C10] AS [C10],
[Project4].[C11] AS [C11],
[Project4].[C12] AS [C12],
[Project4].[C13] AS [C13],
[Project4].[C14] AS [C14],
[Project4].[C15] AS [C15],
[Project4].[C16] AS [C16],
[Project4].[C17] AS [C17],
[Project4].[C18] AS [C18],
[Project4].[C19] AS [C19],
[Project4].[C20] AS [C20],
[Project4].[C21] AS [C21],
[Project4].[C22] AS [C22],
[Project4].[C23] AS [C23],
[Project4].[C24] AS [C24],
[Project4].[C25] AS [C25],
[Project4].[C2] AS [C26],
[Project4].[C26] AS [C27],
[Project4].[C27] AS [C28],
[Project4].[C28] AS [C29],
[Project4].[C29] AS [C30],
[Project4].[C30] AS [C31],
[Project4].[C31] AS [C32],
[Project4].[C32] AS [C33],
[Project4].[C33] AS [C34],
[Project4].[C34] AS [C35],
[Project4].[C35] AS [C36],
[Project4].[C36] AS [C37],
[Project4].[C37] AS [C38],
[Project4].[C38] AS [C39],
[Project4].[C39] AS [C40],
[Project4].[C40] AS [C41],
[Project4].[C41] AS [C42],
[Project4].[C42] AS [C43],
[Project4].[C43] AS [C44],
[Project4].[C44] AS [C45],
[Project4].[C45] AS [C46],
[Project4].[C46] AS [C47],
[Project4].[C47] AS [C48],
[Project4].[C48] AS [C49],
[Project4].[C49] AS [C50],
[Project4].[C50] AS [C51],
[Project4].[C51] AS [C52],
[Project4].[C52] AS [C53],
[Project4].[C53] AS [C54],
[Project4].[C54] AS [C55],
[Project4].[C55] AS [C56],
[Project4].[C56] AS [C57]
FROM ( SELECT
[Project1].[ID] AS [ID],
[Project1].[STATION_ID] AS [STATION_ID],
[Project1].[BATCH_SERIAL_NUMBER] AS [BATCH_SERIAL_NUMBER],
[Project1].[TEST_SOCKET_INDEX] AS [TEST_SOCKET_INDEX],
[Project1].[UUT_SERIAL_NUMBER] AS [UUT_SERIAL_NUMBER],
[Project1].[USER_LOGIN_NAME] AS [USER_LOGIN_NAME],
[Project1].[START_DATE_TIME] AS [START_DATE_TIME],
[Project1].[EXECUTION_TIME] AS [EXECUTION_TIME],
[Project1].[UUT_STATUS] AS [UUT_STATUS],
[Project1].[UUT_ERROR_CODE] AS [UUT_ERROR_CODE],
[Project1].[UUT_ERROR_MESSAGE] AS [UUT_ERROR_MESSAGE],
[Project1].[PART_NUMBER] AS [PART_NUMBER],
[Project1].[TSR_FILE_NAME] AS [TSR_FILE_NAME],
[Project1].[TSR_FILE_ID] AS [TSR_FILE_ID],
[Project1].[TSR_FILE_CLOSED] AS [TSR_FILE_CLOSED],
[Project1].[StationType] AS [StationType],
[Project1].[C1] AS [C1],
[UnionAll1].[C1] AS [C2],
[UnionAll1].[C2] AS [C3],
[UnionAll1].[ID] AS [C4],
[UnionAll1].[UUT_RESULT] AS [C5],
[UnionAll1].[STEP_PARENT] AS [C6],
[UnionAll1].[ORDER_NUMBER] AS [C7],
[UnionAll1].[STEP_NAME] AS [C8],
[UnionAll1].[STEP_TYPE] AS [C9],
[UnionAll1].[STEP_GROUP] AS [C10],
[UnionAll1].[STEP_INDEX] AS [C11],
[UnionAll1].[STEP_ID] AS [C12],
[UnionAll1].[STATUS] AS [C13],
[UnionAll1].[REPORT_TEXT] AS [C14],
[UnionAll1].[ERROR_CODE] AS [C15],
[UnionAll1].[ERROR_MESSAGE] AS [C16],
[UnionAll1].[CAUSED_SEQFAIL] AS [C17],
[UnionAll1].[MODULE_TIME] AS [C18],
[UnionAll1].[TOTAL_TIME] AS [C19],
[UnionAll1].[NUM_LOOPS] AS [C20],
[UnionAll1].[NUM_PASSED] AS [C21],
[UnionAll1].[NUM_FAILED] AS [C22],
[UnionAll1].[ENDING_LOOP_INDEX] AS [C23],
[UnionAll1].[LOOP_INDEX] AS [C24],
[UnionAll1].[INTERACTIVE_EXENUM] AS [C25],
[UnionAll1].[C3] AS [C26],
[UnionAll1].[ID1] AS [C27],
[UnionAll1].[STEP_RESULT] AS [C28],
[UnionAll1].[PROP_PARENT] AS [C29],
[UnionAll1].[ORDER_NUMBER1] AS [C30],
[UnionAll1].[NAME] AS [C31],
[UnionAll1].[PATH] AS [C32],
[UnionAll1].[CATEGORY] AS [C33],
[UnionAll1].[TYPE_VALUE] AS [C34],
[UnionAll1].[TYPE_NAME] AS [C35],
[UnionAll1].[DISPLAY_FORMAT] AS [C36],
[UnionAll1].[DATA] AS [C37],
[UnionAll1].[C4] AS [C38],
[UnionAll1].[ID2] AS [C39],
[UnionAll1].[PROP_RESULT] AS [C40],
[UnionAll1].[COMP_OPERATOR] AS [C41],
[UnionAll1].[HIGH_LIMIT] AS [C42],
[UnionAll1].[LOW_LIMIT] AS [C43],
[UnionAll1].[UNITS] AS [C44],
[UnionAll1].[STATUS1] AS [C45],
[UnionAll1].[C5] AS [C46],
[UnionAll1].[C6] AS [C47],
[UnionAll1].[C7] AS [C48],
[UnionAll1].[C8] AS [C49],
[UnionAll1].[C9] AS [C50],
[UnionAll1].[C10] AS [C51],
[UnionAll1].[C11] AS [C52],
[UnionAll1].[C12] AS [C53],
[UnionAll1].[C13] AS [C54],
[UnionAll1].[C14] AS [C55],
[UnionAll1].[C15] AS [C56],
CASE WHEN ([UnionAll1].[ID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C57]
FROM (SELECT
[Extent1].[ID] AS [ID],
[Extent1].[STATION_ID] AS [STATION_ID],
[Extent1].[BATCH_SERIAL_NUMBER] AS [BATCH_SERIAL_NUMBER],
[Extent1].[TEST_SOCKET_INDEX] AS [TEST_SOCKET_INDEX],
[Extent1].[UUT_SERIAL_NUMBER] AS [UUT_SERIAL_NUMBER],
[Extent1].[USER_LOGIN_NAME] AS [USER_LOGIN_NAME],
[Extent1].[START_DATE_TIME] AS [START_DATE_TIME],
[Extent1].[EXECUTION_TIME] AS [EXECUTION_TIME],
[Extent1].[UUT_STATUS] AS [UUT_STATUS],
[Extent1].[UUT_ERROR_CODE] AS [UUT_ERROR_CODE],
[Extent1].[UUT_ERROR_MESSAGE] AS [UUT_ERROR_MESSAGE],
[Extent1].[PART_NUMBER] AS [PART_NUMBER],
[Extent1].[TSR_FILE_NAME] AS [TSR_FILE_NAME],
[Extent1].[TSR_FILE_ID] AS [TSR_FILE_ID],
[Extent1].[TSR_FILE_CLOSED] AS [TSR_FILE_CLOSED],
[Extent1].[StationType] AS [StationType],
1 AS [C1]
FROM [dbo].[UUT_RESULT] AS [Extent1]
WHERE (([Extent1].[STATION_ID] = #p__linq__0) OR (([Extent1].[STATION_ID] IS NULL) AND (#p__linq__0 IS NULL))) AND ([Extent1].[START_DATE_TIME] >= #p__linq__1) AND ([Extent1].[START_DATE_TIME] <= #p__linq__2) ) AS [Project1]
OUTER APPLY (SELECT
CASE WHEN ([Join1].[ID1] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1],
1 AS [C2],
[Extent2].[ID] AS [ID],
[Extent2].[UUT_RESULT] AS [UUT_RESULT],
[Extent2].[STEP_PARENT] AS [STEP_PARENT],
[Extent2].[ORDER_NUMBER] AS [ORDER_NUMBER],
[Extent2].[STEP_NAME] AS [STEP_NAME],
[Extent2].[STEP_TYPE] AS [STEP_TYPE],
[Extent2].[STEP_GROUP] AS [STEP_GROUP],
[Extent2].[STEP_INDEX] AS [STEP_INDEX],
[Extent2].[STEP_ID] AS [STEP_ID],
[Extent2].[STATUS] AS [STATUS],
[Extent2].[REPORT_TEXT] AS [REPORT_TEXT],
[Extent2].[ERROR_CODE] AS [ERROR_CODE],
[Extent2].[ERROR_MESSAGE] AS [ERROR_MESSAGE],
[Extent2].[CAUSED_SEQFAIL] AS [CAUSED_SEQFAIL],
[Extent2].[MODULE_TIME] AS [MODULE_TIME],
[Extent2].[TOTAL_TIME] AS [TOTAL_TIME],
[Extent2].[NUM_LOOPS] AS [NUM_LOOPS],
[Extent2].[NUM_PASSED] AS [NUM_PASSED],
[Extent2].[NUM_FAILED] AS [NUM_FAILED],
[Extent2].[ENDING_LOOP_INDEX] AS [ENDING_LOOP_INDEX],
[Extent2].[LOOP_INDEX] AS [LOOP_INDEX],
[Extent2].[INTERACTIVE_EXENUM] AS [INTERACTIVE_EXENUM],
CASE WHEN ([Join1].[ID1] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C3],
[Join1].[ID1] AS [ID1],
[Join1].[STEP_RESULT] AS [STEP_RESULT],
[Join1].[PROP_PARENT] AS [PROP_PARENT],
[Join1].[ORDER_NUMBER] AS [ORDER_NUMBER1],
[Join1].[NAME] AS [NAME],
[Join1].[PATH] AS [PATH],
[Join1].[CATEGORY] AS [CATEGORY],
[Join1].[TYPE_VALUE] AS [TYPE_VALUE],
[Join1].[TYPE_NAME] AS [TYPE_NAME],
[Join1].[DISPLAY_FORMAT] AS [DISPLAY_FORMAT],
[Join1].[DATA] AS [DATA],
CASE WHEN ([Join1].[ID1] IS NULL) THEN CAST(NULL AS int) WHEN ([Join1].[ID2] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C4],
[Join1].[ID2] AS [ID2],
[Join1].[PROP_RESULT] AS [PROP_RESULT],
[Join1].[COMP_OPERATOR] AS [COMP_OPERATOR],
[Join1].[HIGH_LIMIT] AS [HIGH_LIMIT],
[Join1].[LOW_LIMIT] AS [LOW_LIMIT],
[Join1].[UNITS] AS [UNITS],
[Join1].[STATUS] AS [STATUS1],
CAST(NULL AS uniqueidentifier) AS [C5],
CAST(NULL AS uniqueidentifier) AS [C6],
CAST(NULL AS uniqueidentifier) AS [C7],
CAST(NULL AS int) AS [C8],
CAST(NULL AS varchar(1)) AS [C9],
CAST(NULL AS varchar(1)) AS [C10],
CAST(NULL AS int) AS [C11],
CAST(NULL AS int) AS [C12],
CAST(NULL AS varchar(1)) AS [C13],
CAST(NULL AS varchar(1)) AS [C14],
CAST(NULL AS varchar(1)) AS [C15]
FROM [dbo].[STEP_RESULT] AS [Extent2]
LEFT OUTER JOIN (SELECT [Extent3].[ID] AS [ID1], [Extent3].[STEP_RESULT] AS [STEP_RESULT], [Extent3].[PROP_PARENT] AS [PROP_PARENT], [Extent3].[ORDER_NUMBER] AS [ORDER_NUMBER], [Extent3].[NAME] AS [NAME], [Extent3].[PATH] AS [PATH], [Extent3].[CATEGORY] AS [CATEGORY], [Extent3].[TYPE_VALUE] AS [TYPE_VALUE], [Extent3].[TYPE_NAME] AS [TYPE_NAME], [Extent3].[DISPLAY_FORMAT] AS [DISPLAY_FORMAT], [Extent3].[DATA] AS [DATA], [Extent4].[ID] AS [ID2], [Extent4].[PROP_RESULT] AS [PROP_RESULT], [Extent4].[COMP_OPERATOR] AS [COMP_OPERATOR], [Extent4].[HIGH_LIMIT] AS [HIGH_LIMIT], [Extent4].[LOW_LIMIT] AS [LOW_LIMIT], [Extent4].[UNITS] AS [UNITS], [Extent4].[STATUS] AS [STATUS]
FROM [dbo].[STEP_NUMERICLIMIT1] AS [Extent3]
LEFT OUTER JOIN [dbo].[STEP_NUMERICLIMIT2] AS [Extent4] ON [Extent3].[ID] = [Extent4].[PROP_RESULT] ) AS [Join1] ON [Extent2].[ID] = [Join1].[STEP_RESULT]
WHERE [Project1].[ID] = [Extent2].[UUT_RESULT]
UNION ALL
SELECT
2 AS [C1],
2 AS [C2],
[Extent5].[ID] AS [ID],
[Extent5].[UUT_RESULT] AS [UUT_RESULT],
[Extent5].[STEP_PARENT] AS [STEP_PARENT],
[Extent5].[ORDER_NUMBER] AS [ORDER_NUMBER],
[Extent5].[STEP_NAME] AS [STEP_NAME],
[Extent5].[STEP_TYPE] AS [STEP_TYPE],
[Extent5].[STEP_GROUP] AS [STEP_GROUP],
[Extent5].[STEP_INDEX] AS [STEP_INDEX],
[Extent5].[STEP_ID] AS [STEP_ID],
[Extent5].[STATUS] AS [STATUS],
[Extent5].[REPORT_TEXT] AS [REPORT_TEXT],
[Extent5].[ERROR_CODE] AS [ERROR_CODE],
[Extent5].[ERROR_MESSAGE] AS [ERROR_MESSAGE],
[Extent5].[CAUSED_SEQFAIL] AS [CAUSED_SEQFAIL],
[Extent5].[MODULE_TIME] AS [MODULE_TIME],
[Extent5].[TOTAL_TIME] AS [TOTAL_TIME],
[Extent5].[NUM_LOOPS] AS [NUM_LOOPS],
[Extent5].[NUM_PASSED] AS [NUM_PASSED],
[Extent5].[NUM_FAILED] AS [NUM_FAILED],
[Extent5].[ENDING_LOOP_INDEX] AS [ENDING_LOOP_INDEX],
[Extent5].[LOOP_INDEX] AS [LOOP_INDEX],
[Extent5].[INTERACTIVE_EXENUM] AS [INTERACTIVE_EXENUM],
CAST(NULL AS int) AS [C3],
CAST(NULL AS uniqueidentifier) AS [C4],
CAST(NULL AS uniqueidentifier) AS [C5],
CAST(NULL AS uniqueidentifier) AS [C6],
CAST(NULL AS int) AS [C7],
CAST(NULL AS varchar(1)) AS [C8],
CAST(NULL AS varchar(1)) AS [C9],
CAST(NULL AS int) AS [C10],
CAST(NULL AS int) AS [C11],
CAST(NULL AS varchar(1)) AS [C12],
CAST(NULL AS varchar(1)) AS [C13],
CAST(NULL AS float) AS [C14],
CAST(NULL AS int) AS [C15],
CAST(NULL AS uniqueidentifier) AS [C16],
CAST(NULL AS uniqueidentifier) AS [C17],
CAST(NULL AS varchar(1)) AS [C18],
CAST(NULL AS float) AS [C19],
CAST(NULL AS float) AS [C20],
CAST(NULL AS varchar(1)) AS [C21],
CAST(NULL AS varchar(1)) AS [C22],
[Extent6].[ID] AS [ID1],
[Extent6].[STEP_RESULT] AS [STEP_RESULT],
[Extent6].[PROP_PARENT] AS [PROP_PARENT],
[Extent6].[ORDER_NUMBER] AS [ORDER_NUMBER1],
[Extent6].[NAME] AS [NAME],
[Extent6].[PATH] AS [PATH],
[Extent6].[CATEGORY] AS [CATEGORY],
[Extent6].[TYPE_VALUE] AS [TYPE_VALUE],
[Extent6].[TYPE_NAME] AS [TYPE_NAME],
[Extent6].[DISPLAY_FORMAT] AS [DISPLAY_FORMAT],
[Extent6].[DATA] AS [DATA]
FROM [dbo].[STEP_RESULT] AS [Extent5]
INNER JOIN [dbo].[PROP_RESULT] AS [Extent6] ON [Extent5].[ID] = [Extent6].[STEP_RESULT]
WHERE [Project1].[ID] = [Extent5].[UUT_RESULT]) AS [UnionAll1]
) AS [Project4]
ORDER BY [Project4].[ID] ASC, [Project4].[C57] ASC, [Project4].[C4] ASC, [Project4].[C2] ASC, [Project4].[C27] ASC, [Project4].[C38] ASC',N'#p__linq__0 varchar(8000),#p__linq__1 datetime2(7),#p__linq__2 datetime2(7)',#p__linq__0='SIDEPCBA',#p__linq__1='2017-08-03 00:00:00',#p__linq__2='2017-08-03 23:59:00'

If you haven't already done it - check what indexes that could/should be created for your specific query. The deault NI SQL database is not indexed or optimized in any way. Run your slow query - and then this query to check what could be done.
-- check what could be indexed
SELECT mig.*, statement AS table_name,
column_id, column_name, column_usage
FROM sys.dm_db_missing_index_details AS mid
CROSS APPLY sys.dm_db_missing_index_columns (mid.index_handle)
INNER JOIN sys.dm_db_missing_index_groups AS mig ON mig.index_handle = mid.index_handle
ORDER BY mig.index_group_handle, mig.index_handle, column_id;

Related

Entity framework groupby and then count individual columns

I have an entity framework query to join applications with ethnicity table and group by ethnicity (Id and options) and then get the total count for each ethnicity and then get the individual counts based on status {open, Closed, Draft.. etc) with Iqueryable as I will need to use pagination for this query to get first 'x' or go to page 'y' so I cannot do toList and then get the values.
The current EF query is very slow and it's taking more time.
Can anyone help me to achieve the same result in a better way if possible?
var query = from app in Context.Application
join eth in Context.Ethnicities on app.EthnicityId equals eth.EthnicityId
group app by new
{
eth.EthnicityId,
eth.EthnicityOptions
}
into ethAgg
select new EthnicityView
{
Id = ethAgg.Key.EthnicityId,
Ethnicity = ethAgg.Key.EthnicityOptions,
Total = ethAgg.Count(),
Closed = ethAgg.Count(p => p.Closed),
Draft = ethAgg.Count(p => p.Draft ),
Inprogress = ethAgg.Count(p => p.Inprogress ),
Waiting = ethAgg.Count(p => p.Waiting),
Open = ethAgg.Count(p => p.Open )
};
Generated Sql
SELECT TOP (10)
[Project7].[EthnicityID] AS [EthnicityID],
[Project7].[C2] AS [C1],
[Project7].[C1] AS [C2],
[Project7].[C3] AS [C3],
[Project7].[C4] AS [C4],
[Project7].[C5] AS [C5],
[Project7].[C6] AS [C6],
[Project7].[C7] AS [C7]
FROM ( SELECT
[Project6].[C1] AS [C1],
[Project6].[EthnicityID] AS [EthnicityID],
[Project6].[EthnicityOptions] AS [C2],
[Project6].[C2] AS [C3],
[Project6].[C3] AS [C4],
[Project6].[C4] AS [C5],
[Project6].[C5] AS [C6],
[Project6].[C6] AS [C7]
FROM ( SELECT
[Project5].[C1] AS [C1],
[Project5].[EthnicityID] AS [EthnicityID],
[Project5].[EthnicityOptions] AS [EthnicityOptions],
[Project5].[C2] AS [C2],
[Project5].[C3] AS [C3],
[Project5].[C4] AS [C4],
[Project5].[C5] AS [C5],
(SELECT
COUNT(1) AS [A1]
FROM [dbo].[Application] AS [Extent16]
INNER JOIN [dbo].[Ethnicity] AS [Extent18] ON [Extent16].[EthnicityID] = [Extent18].[EthnicityID]
WHERE ([Extent16].[Closed] = 1)
FROM ( SELECT
[Project4].[C1] AS [C1],
[Project4].[EthnicityID] AS [EthnicityID],
[Project4].[EthnicityOptions] AS [EthnicityOptions],
[Project4].[C2] AS [C2],
[Project4].[C3] AS [C3],
[Project4].[C4] AS [C4],
(SELECT
COUNT(1) AS [A1]
FROM [dbo].[Application] AS [Extent13]
INNER JOIN [dbo].[Ethnicity] AS [Extent15] ON [Extent13].[EthnicityID] = [Extent15].[EthnicityID]
WHERE ([Extent13].[Closed] = 1)
FROM ( SELECT
[Project3].[C1] AS [C1],
[Project3].[EthnicityID] AS [EthnicityID],
[Project3].[EthnicityOptions] AS [EthnicityOptions],
[Project3].[C2] AS [C2],
[Project3].[C3] AS [C3],
(SELECT
COUNT(1) AS [A1]
FROM [dbo].[Application] AS [Extent10]
INNER JOIN [dbo].[Ethnicity] AS [Extent12] ON [Extent10].[EthnicityID] = [Extent12].[EthnicityID]
WHERE ([Extent10].[Draft] = 1)
FROM ( SELECT
[Project2].[C1] AS [C1],
[Project2].[EthnicityID] AS [EthnicityID],
[Project2].[EthnicityOptions] AS [EthnicityOptions],
[Project2].[C2] AS [C2],
(SELECT
COUNT(1) AS [A1]
FROM [dbo].[Application] AS [Extent7]
INNER JOIN [dbo].[Ethnicity] AS [Extent9] ON [Extent7].[EthnicityID] = [Extent9].[EthnicityID]
WHERE ([Extent7].[Inprogress] = 1)
FROM ( SELECT
[Project1].[C1] AS [C1],
[Project1].[EthnicityID] AS [EthnicityID],
[Project1].[EthnicityOptions] AS [EthnicityOptions],
(SELECT
COUNT(1) AS [A1]
FROM [dbo].[Application] AS [Extent4]
INNER JOIN [dbo].[Ethnicity] AS [Extent6] ON [Extent4].[EthnicityID] = [Extent6].[EthnicityID]
WHERE ([Extent4].[Waiting] = 1)
FROM ( SELECT
[GroupBy1].[A1] AS [C1],
[GroupBy1].[K1] AS [EthnicityID],
[GroupBy1].[K2] AS [EthnicityOptions]
FROM ( SELECT
[Extent3].[EthnicityID] AS [K1],
[Extent3].[EthnicityOptions] AS [K2],
COUNT(1) AS [A1]
FROM [dbo].[Application] AS [Extent1]
INNER JOIN [dbo].[Ethnicity] AS [Extent3] ON [Extent1].[EthnicityID] = [Extent3].[EthnicityID]
GROUP BY [Extent3].[EthnicityID], [Extent3].[EthnicityOptions]
) AS [GroupBy1]
) AS [Project1]
) AS [Project2]
) AS [Project3]
) AS [Project4]
) AS [Project5]
) AS [Project6]
) AS [Project7]
ORDER BY [Project7].[EthnicityID] ASC
As there is no way we could achieve this from entity framework.
I tried moving this query to a stored procedure and split the individual counts and invoke that stored proc from entity framework.

Why does Take() return more rows than specified?

I am querying a database with Entity Framework. To limit the results I am using Take(1000). The problem is that EF returns more than 1000 rows, and all entities after #1000 do not contain correct data.
This is the table structure:
And the query looks like this:
var resultListTmp = db.TinglysEjendom.Where(x => x.EjdStatus == description)
.Include(x => x.TinglysEjd_ESR.Select(y => y.ESR))
.Include(nameof(TingLysMatrikkel))
.Take(amount).AsNoTracking().ToList();
The problem is that all TinglysEjendom entities after #1000 do not have any TinglysMatrikkel relations, but in the database they do.
When removing:
.Include(x => x.TinglysEjd_ESR.Select(y => y.ESR))
from the query, EF returns correct number of rows.
The column MatrikkelNummer in the TinglysMatrikkel table can (amongst others) take the values:
æ
ø
å
Someone suggested it might be an i18n "Internationalization and localization" problem. Im not sure how this could be. Maybe someone could point me in the right direction?
Thanks in advance
LINQ translates the above query in to:
exec sp_executesql N'SELECT
[UnionAll1].[EjdId] AS [C1],
[UnionAll1].[EjdId1] AS [C2],
[UnionAll1].[EjdType] AS [C3],
[UnionAll1].[BygningsNr] AS [C4],
[UnionAll1].[TimeshareNr] AS [C5],
[UnionAll1].[AnpartsNr] AS [C6],
[UnionAll1].[EjerLejNr] AS [C7],
[UnionAll1].[Beskrivelse] AS [C8],
[UnionAll1].[StreetBuildingIdentifier] AS [C9],
[UnionAll1].[EjdStatus] AS [C10],
[UnionAll1].[StatusTimestamp] AS [C11],
[UnionAll1].[IAbonnement] AS [C12],
[UnionAll1].[AbonnementOpretAttempts] AS [C13],
[UnionAll1].[AbonnementsId] AS [C14],
[UnionAll1].[BestemtFastEjendomsNummer] AS [C15],
[UnionAll1].[UpdateToken] AS [C16],
[UnionAll1].[FaellesEjendomIdentifikator] AS [C17],
[UnionAll1].[C1] AS [C18],
[UnionAll1].[ESRId] AS [C19],
[UnionAll1].[ESRId1] AS [C20],
[UnionAll1].[EjdId2] AS [C21],
[UnionAll1].[Passiv] AS [C22],
[UnionAll1].[ESRId2] AS [C23],
[UnionAll1].[EjdId3] AS [C24],
[UnionAll1].[ESRId3] AS [C25],
[UnionAll1].[ESR_Kommune] AS [C26],
[UnionAll1].[ESR_EjdNummer] AS [C27],
[UnionAll1].[UdgaaetCognito] AS [C28],
[UnionAll1].[Status] AS [C29],
[UnionAll1].[C2] AS [C30],
[UnionAll1].[C3] AS [C31],
[UnionAll1].[C4] AS [C32],
[UnionAll1].[C5] AS [C33]
FROM (SELECT
CASE WHEN ([Join1].[ESRId1] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1],
[Limit1].[EjdId] AS [EjdId],
[Limit1].[EjdId] AS [EjdId1],
[Limit1].[EjdType] AS [EjdType],
[Limit1].[BygningsNr] AS [BygningsNr],
[Limit1].[TimeshareNr] AS [TimeshareNr],
[Limit1].[AnpartsNr] AS [AnpartsNr],
[Limit1].[EjerLejNr] AS [EjerLejNr],
[Limit1].[Beskrivelse] AS [Beskrivelse],
[Limit1].[StreetBuildingIdentifier] AS [StreetBuildingIdentifier],
[Limit1].[EjdStatus] AS [EjdStatus],
[Limit1].[StatusTimestamp] AS [StatusTimestamp],
[Limit1].[IAbonnement] AS [IAbonnement],
[Limit1].[AbonnementOpretAttempts] AS [AbonnementOpretAttempts],
[Limit1].[AbonnementsId] AS [AbonnementsId],
[Limit1].[BestemtFastEjendomsNummer] AS [BestemtFastEjendomsNummer],
[Limit1].[UpdateToken] AS [UpdateToken],
[Limit1].[FaellesEjendomIdentifikator] AS [FaellesEjendomIdentifikator],
[Join1].[ESRId1] AS [ESRId],
[Join1].[ESRId1] AS [ESRId1],
[Join1].[EjdId] AS [EjdId2],
[Join1].[Passiv] AS [Passiv],
[Join1].[ESRId1] AS [ESRId2],
[Join1].[EjdId] AS [EjdId3],
[Join1].[ESRId2] AS [ESRId3],
[Join1].[ESR_Kommune] AS [ESR_Kommune],
[Join1].[ESR_EjdNummer] AS [ESR_EjdNummer],
[Join1].[UdgaaetCognito] AS [UdgaaetCognito],
[Join1].[Status] AS [Status],
CAST(NULL AS int) AS [C2],
CAST(NULL AS varchar(1)) AS [C3],
CAST(NULL AS varchar(1)) AS [C4],
CAST(NULL AS int) AS [C5]
FROM (SELECT TOP (1000)
[Extent1].[EjdId] AS [EjdId],
[Extent1].[EjdType] AS [EjdType],
[Extent1].[BygningsNr] AS [BygningsNr],
[Extent1].[TimeshareNr] AS [TimeshareNr],
[Extent1].[AnpartsNr] AS [AnpartsNr],
[Extent1].[EjerLejNr] AS [EjerLejNr],
[Extent1].[Beskrivelse] AS [Beskrivelse],
[Extent1].[StreetBuildingIdentifier] AS [StreetBuildingIdentifier],
[Extent1].[EjdStatus] AS [EjdStatus],
[Extent1].[StatusTimestamp] AS [StatusTimestamp],
[Extent1].[IAbonnement] AS [IAbonnement],
[Extent1].[AbonnementOpretAttempts] AS [AbonnementOpretAttempts],
[Extent1].[AbonnementsId] AS [AbonnementsId],
[Extent1].[BestemtFastEjendomsNummer] AS [BestemtFastEjendomsNummer],
[Extent1].[UpdateToken] AS [UpdateToken],
[Extent1].[FaellesEjendomIdentifikator] AS [FaellesEjendomIdentifikator]
FROM [dbo].[TinglysEjendom] AS [Extent1]
WHERE [Extent1].[EjdStatus] = #p__linq__0 ) AS [Limit1]
LEFT OUTER JOIN (SELECT [Extent2].[ESRId] AS [ESRId1], [Extent2].[EjdId] AS [EjdId], [Extent2].[Passiv] AS [Passiv], [Extent3].[ESRId] AS [ESRId2], [Extent3].[ESR_Kommune] AS [ESR_Kommune], [Extent3].[ESR_EjdNummer] AS [ESR_EjdNummer], [Extent3].[UdgaaetCognito] AS [UdgaaetCognito], [Extent3].[Status] AS [Status]
FROM [dbo].[TinglysEjd_ESR] AS [Extent2]
INNER JOIN [dbo].[ESR] AS [Extent3] ON [Extent2].[ESRId] = [Extent3].[ESRId] ) AS [Join1] ON [Limit1].[EjdId] = [Join1].[EjdId]
UNION ALL
SELECT
2 AS [C1],
[Limit2].[EjdId] AS [EjdId],
[Limit2].[EjdId] AS [EjdId1],
[Limit2].[EjdType] AS [EjdType],
[Limit2].[BygningsNr] AS [BygningsNr],
[Limit2].[TimeshareNr] AS [TimeshareNr],
[Limit2].[AnpartsNr] AS [AnpartsNr],
[Limit2].[EjerLejNr] AS [EjerLejNr],
[Limit2].[Beskrivelse] AS [Beskrivelse],
[Limit2].[StreetBuildingIdentifier] AS [StreetBuildingIdentifier],
[Limit2].[EjdStatus] AS [EjdStatus],
[Limit2].[StatusTimestamp] AS [StatusTimestamp],
[Limit2].[IAbonnement] AS [IAbonnement],
[Limit2].[AbonnementOpretAttempts] AS [AbonnementOpretAttempts],
[Limit2].[AbonnementsId] AS [AbonnementsId],
[Limit2].[BestemtFastEjendomsNummer] AS [BestemtFastEjendomsNummer],
[Limit2].[UpdateToken] AS [UpdateToken],
[Limit2].[FaellesEjendomIdentifikator] AS [FaellesEjendomIdentifikator],
CAST(NULL AS int) AS [C2],
CAST(NULL AS int) AS [C3],
CAST(NULL AS int) AS [C4],
CAST(NULL AS bit) AS [C5],
CAST(NULL AS int) AS [C6],
CAST(NULL AS int) AS [C7],
CAST(NULL AS int) AS [C8],
CAST(NULL AS int) AS [C9],
CAST(NULL AS int) AS [C10],
CAST(NULL AS bit) AS [C11],
CAST(NULL AS varchar(1)) AS [C12],
[Extent5].[EjdId] AS [EjdId2],
[Extent5].[LandsEjerlavKode] AS [LandsEjerlavKode],
[Extent5].[MatrikkelNummer] AS [MatrikkelNummer],
[Extent5].[EjdId] AS [EjdId3]
FROM (SELECT TOP (1000)
[Extent4].[EjdId] AS [EjdId],
[Extent4].[EjdType] AS [EjdType],
[Extent4].[BygningsNr] AS [BygningsNr],
[Extent4].[TimeshareNr] AS [TimeshareNr],
[Extent4].[AnpartsNr] AS [AnpartsNr],
[Extent4].[EjerLejNr] AS [EjerLejNr],
[Extent4].[Beskrivelse] AS [Beskrivelse],
[Extent4].[StreetBuildingIdentifier] AS [StreetBuildingIdentifier],
[Extent4].[EjdStatus] AS [EjdStatus],
[Extent4].[StatusTimestamp] AS [StatusTimestamp],
[Extent4].[IAbonnement] AS [IAbonnement],
[Extent4].[AbonnementOpretAttempts] AS [AbonnementOpretAttempts],
[Extent4].[AbonnementsId] AS [AbonnementsId],
[Extent4].[BestemtFastEjendomsNummer] AS [BestemtFastEjendomsNummer],
[Extent4].[UpdateToken] AS [UpdateToken],
[Extent4].[FaellesEjendomIdentifikator] AS [FaellesEjendomIdentifikator]
FROM [dbo].[TinglysEjendom] AS [Extent4]
WHERE [Extent4].[EjdStatus] = #p__linq__0 ) AS [Limit2]
INNER JOIN [dbo].[TingLysMatrikkel] AS [Extent5] ON [Limit2].[EjdId] = [Extent5].[EjdId]) AS [UnionAll1]
ORDER BY [UnionAll1].[EjdId1] ASC, [UnionAll1].[C1] ASC',N'#p__linq__0 nvarchar(4000)',#p__linq__0=N'HentData'
This looks like a somewhat unreliable query at the C# part. That said, it's up to Entity Framework to translate it to SQL that does what you asked, and it's failing to do that. It may be worth reporting as a bug if it hasn't been already.
If you look closely in your SQL, you'll find two separate queries using TOP (1000) combined by UNION ALL. However, neither of those queries is using any ORDER BY, therefore there's nothing preventing SQL Server from picking a different set of 1000 records, which it may do if e.g. it can use a different index for the first part of the query compared to the second.
You should be able to work around it by specifying which first 1000 records you want returned. If you don't care about the order, just order them by ID.

Full text index search for complex query in Entity framework

I am trying to perform full text index search using EF 6.0. I am using IDbCommandInterceptor (http://www.entityframework.info/Home/FullTextSearch) perform Full text search but it is throwing me this exception:
Cannot use a CONTAINS or FREETEXT predicate on column 'FirstName'
because it is not full-text indexed.
Linq query:
ListOfEmployees = _context.EmployeeCvs.Include(x => x.Employee)
.Include(x => x.Tags)
.Include(x => x.ProjectExperiences)
.Where(x => x.Employee.FirstName.Contains(SearchQuery.Keyword) || x.Employee.LastName.Contains(SearchQuery.Keyword) || x.ProjectExperiences.Any(y => y.ProjectTitle.Contains(SearchQuery.Keyword) || y.Description.Contains(SearchQuery.Keyword)) || x.Tags.Any(t => t.Title.Contains(SearchQuery.Keyword)))
.ToList();
Below is the query that is executed by EF:
exec sp_executesql N'SELECT
[UnionAll1].[Id] AS [C1],
[UnionAll1].[Id1] AS [C2],
[UnionAll1].[Id2] AS [C3],
[UnionAll1].[Id3] AS [C4],
[UnionAll1].[Id4] AS [C5],
[UnionAll1].[Id5] AS [C6],
[UnionAll1].[Id6] AS [C7],
[UnionAll1].[Id7] AS [C8],
[UnionAll1].[Id8] AS [C9],
[UnionAll1].[FirstName] AS [C10],
[UnionAll1].[LastName] AS [C11],
[UnionAll1].[EnterpriseId] AS [C12],
[UnionAll1].[Level] AS [C13],
[UnionAll1].[C1] AS [C14],
[UnionAll1].[Id9] AS [C15],
[UnionAll1].[Id10] AS [C16],
[UnionAll1].[Title] AS [C17],
[UnionAll1].[CreatedDate] AS [C18],
[UnionAll1].[CreatedBy] AS [C19],
[UnionAll1].[UpdatedDate] AS [C20],
[UnionAll1].[UpdatedBy] AS [C21],
[UnionAll1].[IsDeleted] AS [C22],
[UnionAll1].[TagType_Id] AS [C23],
[UnionAll1].[ProjectExperience_Id] AS [C24],
[UnionAll1].[C2] AS [C25],
[UnionAll1].[C3] AS [C26],
[UnionAll1].[C4] AS [C27],
[UnionAll1].[C5] AS [C28],
[UnionAll1].[C6] AS [C29],
[UnionAll1].[C7] AS [C30],
[UnionAll1].[C8] AS [C31],
[UnionAll1].[C9] AS [C32],
[UnionAll1].[C10] AS [C33],
[UnionAll1].[C11] AS [C34],
[UnionAll1].[C12] AS [C35],
[UnionAll1].[C13] AS [C36],
[UnionAll1].[C14] AS [C37],
[UnionAll1].[C15] AS [C38],
[UnionAll1].[C16] AS [C39],
[UnionAll1].[C17] AS [C40]
FROM (SELECT
CASE WHEN ([Join7].[FKEmployeeCvId] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1],
[Extent1].[Id] AS [Id],
[Extent2].[Id] AS [Id1],
[Extent3].[Id] AS [Id2],
[Extent4].[Id] AS [Id3],
[Extent5].[Id] AS [Id4],
[Extent6].[Id] AS [Id5],
[Extent7].[Id] AS [Id6],
[Extent1].[Id] AS [Id7],
[Extent1].[Id] AS [Id8],
[Extent4].[FirstName] AS [FirstName],
[Extent5].[LastName] AS [LastName],
[Extent6].[EnterpriseId] AS [EnterpriseId],
[Extent7].[Level] AS [Level],
[Join7].[Id] AS [Id9],
[Join7].[Id] AS [Id10],
[Join7].[Title] AS [Title],
[Join7].[CreatedDate] AS [CreatedDate],
[Join7].[CreatedBy] AS [CreatedBy],
[Join7].[UpdatedDate] AS [UpdatedDate],
[Join7].[UpdatedBy] AS [UpdatedBy],
[Join7].[IsDeleted] AS [IsDeleted],
[Join7].[TagType_Id] AS [TagType_Id],
[Join7].[ProjectExperience_Id] AS [ProjectExperience_Id],
CAST(NULL AS int) AS [C2],
CAST(NULL AS varchar(1)) AS [C3],
CAST(NULL AS int) AS [C4],
CAST(NULL AS varchar(1)) AS [C5],
CAST(NULL AS varchar(1)) AS [C6],
CAST(NULL AS datetime2) AS [C7],
CAST(NULL AS varchar(1)) AS [C8],
CAST(NULL AS datetime2) AS [C9],
CAST(NULL AS varchar(1)) AS [C10],
CAST(NULL AS bit) AS [C11],
CAST(NULL AS int) AS [C12],
CAST(NULL AS int) AS [C13],
CAST(NULL AS int) AS [C14],
CAST(NULL AS int) AS [C15],
CAST(NULL AS int) AS [C16],
CAST(NULL AS int) AS [C17]
FROM (SELECT [Var_41].[Id] AS [Id], [Var_41].[Employee_Id] AS [Employee_Id]
FROM [dbo].[EmployeeCv] AS [Var_41]
WHERE ([Var_41].[IsDeleted] = #DynamicFilterParam_IsDeleted_IsDeleted) OR (#DynamicFilterParam_IsDeleted_DynamicFilterIsDisabled IS NOT NULL) ) AS [Extent1]
LEFT OUTER JOIN (SELECT [Var_42].[Id] AS [Id], [Var_42].[FirstName] AS [FirstName], [Var_42].[Discriminator] AS [Discriminator]
FROM [dbo].[Employee] AS [Var_42]
WHERE ([Var_42].[IsDeleted] = #DynamicFilterParam_IsDeleted_IsDeleted) OR (#DynamicFilterParam_IsDeleted_DynamicFilterIsDisabled IS NOT NULL) ) AS [Extent2] ON ([Extent2].[Discriminator] = N''Employee'') AND ([Extent1].[Employee_Id] = [Extent2].[Id])
LEFT OUTER JOIN (SELECT [Var_43].[Id] AS [Id], [Var_43].[LastName] AS [LastName], [Var_43].[Discriminator] AS [Discriminator]
FROM [dbo].[Employee] AS [Var_43]
WHERE ([Var_43].[IsDeleted] = #DynamicFilterParam_IsDeleted_IsDeleted) OR (#DynamicFilterParam_IsDeleted_DynamicFilterIsDisabled IS NOT NULL) ) AS [Extent3] ON ([Extent3].[Discriminator] = N''Employee'') AND ([Extent1].[Employee_Id] = [Extent3].[Id])
LEFT OUTER JOIN (SELECT [Var_44].[Id] AS [Id], [Var_44].[FirstName] AS [FirstName], [Var_44].[Discriminator] AS [Discriminator]
FROM [dbo].[Employee] AS [Var_44]
WHERE ([Var_44].[IsDeleted] = #DynamicFilterParam_IsDeleted_IsDeleted) OR (#DynamicFilterParam_IsDeleted_DynamicFilterIsDisabled IS NOT NULL) ) AS [Extent4] ON ([Extent4].[Discriminator] = N''Employee'') AND ([Extent1].[Employee_Id] = [Extent4].[Id])
LEFT OUTER JOIN (SELECT [Var_45].[Id] AS [Id], [Var_45].[LastName] AS [LastName], [Var_45].[Discriminator] AS [Discriminator]
FROM [dbo].[Employee] AS [Var_45]
WHERE ([Var_45].[IsDeleted] = #DynamicFilterParam_IsDeleted_IsDeleted) OR (#DynamicFilterParam_IsDeleted_DynamicFilterIsDisabled IS NOT NULL) ) AS [Extent5] ON ([Extent5].[Discriminator] = N''Employee'') AND ([Extent1].[Employee_Id] = [Extent5].[Id])
LEFT OUTER JOIN (SELECT [Var_46].[Id] AS [Id], [Var_46].[EnterpriseId] AS [EnterpriseId], [Var_46].[Discriminator] AS [Discriminator]
FROM [dbo].[Employee] AS [Var_46]
WHERE ([Var_46].[IsDeleted] = #DynamicFilterParam_IsDeleted_IsDeleted) OR (#DynamicFilterParam_IsDeleted_DynamicFilterIsDisabled IS NOT NULL) ) AS [Extent6] ON ([Extent6].[Discriminator] = N''Employee'') AND ([Extent1].[Employee_Id] = [Extent6].[Id])
LEFT OUTER JOIN (SELECT [Var_47].[Id] AS [Id], [Var_47].[Level] AS [Level], [Var_47].[Discriminator] AS [Discriminator]
FROM [dbo].[Employee] AS [Var_47]
WHERE ([Var_47].[IsDeleted] = #DynamicFilterParam_IsDeleted_IsDeleted) OR (#DynamicFilterParam_IsDeleted_DynamicFilterIsDisabled IS NOT NULL) ) AS [Extent7] ON ([Extent7].[Discriminator] = N''Employee'') AND ([Extent1].[Employee_Id] = [Extent7].[Id])
LEFT OUTER JOIN (SELECT [Extent8].[FKEmployeeCvId] AS [FKEmployeeCvId], [Extent9].[Id] AS [Id], [Extent9].[Title] AS [Title], [Extent9].[CreatedDate] AS [CreatedDate], [Extent9].[CreatedBy] AS [CreatedBy], [Extent9].[UpdatedDate] AS [UpdatedDate], [Extent9].[UpdatedBy] AS [UpdatedBy], [Extent9].[IsDeleted] AS [IsDeleted], [Extent9].[TagType_Id] AS [TagType_Id], [Extent9].[ProjectExperience_Id] AS [ProjectExperience_Id]
FROM [dbo].[EmployeeTags] AS [Extent8]
INNER JOIN (SELECT [Var_48].[Id] AS [Id], [Var_48].[Title] AS [Title], [Var_48].[CreatedDate] AS [CreatedDate], [Var_48].[CreatedBy] AS [CreatedBy], [Var_48].[UpdatedDate] AS [UpdatedDate], [Var_48].[UpdatedBy] AS [UpdatedBy], [Var_48].[IsDeleted] AS [IsDeleted], [Var_48].[TagType_Id] AS [TagType_Id], [Var_48].[ProjectExperience_Id] AS [ProjectExperience_Id]
FROM [dbo].[Tag] AS [Var_48]
WHERE ([Var_48].[IsDeleted] = #DynamicFilterParam_IsDeleted_IsDeleted) OR (#DynamicFilterParam_IsDeleted_DynamicFilterIsDisabled IS NOT NULL) ) AS [Extent9] ON [Extent9].[Id] = [Extent8].[FKTagId] ) AS [Join7] ON [Extent1].[Id] = [Join7].[FKEmployeeCvId]
WHERE (contains([Extent2].[FirstName], #p__linq__0)) OR (contains([Extent3].[LastName], #p__linq__1)) OR ( EXISTS (SELECT
1 AS [C1]
FROM [dbo].[ProjectExperience] AS [Extent10]
WHERE (([Extent10].[IsDeleted] = #DynamicFilterParam_IsDeleted_IsDeleted) OR (#DynamicFilterParam_IsDeleted_DynamicFilterIsDisabled IS NOT NULL)) AND ([Extent10].[Type] = N''Draft'') AND ([Extent1].[Id] = [Extent10].[EmployeeCv_Id]) AND ((contains([Extent10].[ProjectTitle], #p__linq__2)) OR (contains([Extent10].[Description], #p__linq__3)))
)) OR ( EXISTS (SELECT
1 AS [C1]
FROM [dbo].[EmployeeTags] AS [Extent11]
INNER JOIN (SELECT [Var_49].[Id] AS [Id], [Var_49].[Title] AS [Title]
FROM [dbo].[Tag] AS [Var_49]
WHERE ([Var_49].[IsDeleted] = #DynamicFilterParam_IsDeleted_IsDeleted) OR (#DynamicFilterParam_IsDeleted_DynamicFilterIsDisabled IS NOT NULL) ) AS [Extent12] ON [Extent12].[Id] = [Extent11].[FKTagId]
WHERE ([Extent1].[Id] = [Extent11].[FKEmployeeCvId]) AND (contains([Extent12].[Title], #p__linq__4))
))
UNION ALL
SELECT
2 AS [C1],
[Extent13].[Id] AS [Id],
[Extent14].[Id] AS [Id1],
[Extent15].[Id] AS [Id2],
[Extent16].[Id] AS [Id3],
[Extent17].[Id] AS [Id4],
[Extent18].[Id] AS [Id5],
[Extent19].[Id] AS [Id6],
[Extent13].[Id] AS [Id7],
[Extent13].[Id] AS [Id8],
[Extent16].[FirstName] AS [FirstName],
[Extent17].[LastName] AS [LastName],
[Extent18].[EnterpriseId] AS [EnterpriseId],
[Extent19].[Level] AS [Level],
CAST(NULL AS int) AS [C2],
CAST(NULL AS int) AS [C3],
CAST(NULL AS varchar(1)) AS [C4],
CAST(NULL AS datetime2) AS [C5],
CAST(NULL AS varchar(1)) AS [C6],
CAST(NULL AS datetime2) AS [C7],
CAST(NULL AS varchar(1)) AS [C8],
CAST(NULL AS bit) AS [C9],
CAST(NULL AS int) AS [C10],
CAST(NULL AS int) AS [C11],
[Extent20].[Id] AS [Id9],
''4X0X'' AS [C12],
[Extent20].[Id] AS [Id10],
[Extent20].[ProjectTitle] AS [ProjectTitle],
[Extent20].[Description] AS [Description],
[Extent20].[CreatedDate] AS [CreatedDate],
[Extent20].[CreatedBy] AS [CreatedBy],
[Extent20].[UpdatedDate] AS [UpdatedDate],
[Extent20].[UpdatedBy] AS [UpdatedBy],
[Extent20].[IsDeleted] AS [IsDeleted],
[Extent20].[SequenceOrder] AS [SequenceOrder],
[Extent20].[EmployeeCv_Id] AS [EmployeeCv_Id],
[Extent20].[CvProfile_Id] AS [CvProfile_Id],
[Extent20].[AssociatedSchedulingProject_Id] AS [AssociatedSchedulingProject_Id],
[Extent20].[Customer_Id] AS [Customer_Id],
[Extent20].[Employee_Id] AS [Employee_Id]
FROM (SELECT [Var_50].[Id] AS [Id], [Var_50].[Employee_Id] AS [Employee_Id]
FROM [dbo].[EmployeeCv] AS [Var_50]
WHERE ([Var_50].[IsDeleted] = #DynamicFilterParam_IsDeleted_IsDeleted) OR (#DynamicFilterParam_IsDeleted_DynamicFilterIsDisabled IS NOT NULL) ) AS [Extent13]
LEFT OUTER JOIN (SELECT [Var_51].[Id] AS [Id], [Var_51].[FirstName] AS [FirstName], [Var_51].[Discriminator] AS [Discriminator]
FROM [dbo].[Employee] AS [Var_51]
WHERE ([Var_51].[IsDeleted] = #DynamicFilterParam_IsDeleted_IsDeleted) OR (#DynamicFilterParam_IsDeleted_DynamicFilterIsDisabled IS NOT NULL) ) AS [Extent14] ON ([Extent14].[Discriminator] = N''Employee'') AND ([Extent13].[Employee_Id] = [Extent14].[Id])
LEFT OUTER JOIN (SELECT [Var_52].[Id] AS [Id], [Var_52].[LastName] AS [LastName], [Var_52].[Discriminator] AS [Discriminator]
FROM [dbo].[Employee] AS [Var_52]
WHERE ([Var_52].[IsDeleted] = #DynamicFilterParam_IsDeleted_IsDeleted) OR (#DynamicFilterParam_IsDeleted_DynamicFilterIsDisabled IS NOT NULL) ) AS [Extent15] ON ([Extent15].[Discriminator] = N''Employee'') AND ([Extent13].[Employee_Id] = [Extent15].[Id])
LEFT OUTER JOIN (SELECT [Var_53].[Id] AS [Id], [Var_53].[FirstName] AS [FirstName], [Var_53].[Discriminator] AS [Discriminator]
FROM [dbo].[Employee] AS [Var_53]
WHERE ([Var_53].[IsDeleted] = #DynamicFilterParam_IsDeleted_IsDeleted) OR (#DynamicFilterParam_IsDeleted_DynamicFilterIsDisabled IS NOT NULL) ) AS [Extent16] ON ([Extent16].[Discriminator] = N''Employee'') AND ([Extent13].[Employee_Id] = [Extent16].[Id])
LEFT OUTER JOIN (SELECT [Var_54].[Id] AS [Id], [Var_54].[LastName] AS [LastName], [Var_54].[Discriminator] AS [Discriminator]
FROM [dbo].[Employee] AS [Var_54]
WHERE ([Var_54].[IsDeleted] = #DynamicFilterParam_IsDeleted_IsDeleted) OR (#DynamicFilterParam_IsDeleted_DynamicFilterIsDisabled IS NOT NULL) ) AS [Extent17] ON ([Extent17].[Discriminator] = N''Employee'') AND ([Extent13].[Employee_Id] = [Extent17].[Id])
LEFT OUTER JOIN (SELECT [Var_55].[Id] AS [Id], [Var_55].[EnterpriseId] AS [EnterpriseId], [Var_55].[Discriminator] AS [Discriminator]
FROM [dbo].[Employee] AS [Var_55]
WHERE ([Var_55].[IsDeleted] = #DynamicFilterParam_IsDeleted_IsDeleted) OR (#DynamicFilterParam_IsDeleted_DynamicFilterIsDisabled IS NOT NULL) ) AS [Extent18] ON ([Extent18].[Discriminator] = N''Employee'') AND ([Extent13].[Employee_Id] = [Extent18].[Id])
LEFT OUTER JOIN (SELECT [Var_56].[Id] AS [Id], [Var_56].[Level] AS [Level], [Var_56].[Discriminator] AS [Discriminator]
FROM [dbo].[Employee] AS [Var_56]
WHERE ([Var_56].[IsDeleted] = #DynamicFilterParam_IsDeleted_IsDeleted) OR (#DynamicFilterParam_IsDeleted_DynamicFilterIsDisabled IS NOT NULL) ) AS [Extent19] ON ([Extent19].[Discriminator] = N''Employee'') AND ([Extent13].[Employee_Id] = [Extent19].[Id])
INNER JOIN (SELECT [Var_57].[Id] AS [Id], [Var_57].[ProjectTitle] AS [ProjectTitle], [Var_57].[Description] AS [Description], [Var_57].[CreatedDate] AS [CreatedDate], [Var_57].[CreatedBy] AS [CreatedBy], [Var_57].[UpdatedDate] AS [UpdatedDate], [Var_57].[UpdatedBy] AS [UpdatedBy], [Var_57].[IsDeleted] AS [IsDeleted], [Var_57].[SequenceOrder] AS [SequenceOrder], [Var_57].[EmployeeCv_Id] AS [EmployeeCv_Id], [Var_57].[CvProfile_Id] AS [CvProfile_Id], [Var_57].[AssociatedSchedulingProject_Id] AS [AssociatedSchedulingProject_Id], [Var_57].[Customer_Id] AS [Customer_Id], [Var_57].[Employee_Id] AS [Employee_Id], [Var_57].[Type] AS [Type]
FROM [dbo].[ProjectExperience] AS [Var_57]
WHERE ([Var_57].[IsDeleted] = #DynamicFilterParam_IsDeleted_IsDeleted) OR (#DynamicFilterParam_IsDeleted_DynamicFilterIsDisabled IS NOT NULL) ) AS [Extent20] ON ([Extent20].[Type] = N''Draft'') AND ([Extent13].[Id] = [Extent20].[EmployeeCv_Id])
WHERE (contains([Extent14].[FirstName], #p__linq__0)) OR (contains([Extent15].[LastName], #p__linq__1)) OR ( EXISTS (SELECT
1 AS [C1]
FROM [dbo].[ProjectExperience] AS [Extent21]
WHERE (([Extent21].[IsDeleted] = #DynamicFilterParam_IsDeleted_IsDeleted) OR (#DynamicFilterParam_IsDeleted_DynamicFilterIsDisabled IS NOT NULL)) AND ([Extent21].[Type] = N''Draft'') AND ([Extent13].[Id] = [Extent21].[EmployeeCv_Id]) AND ((contains([Extent21].[ProjectTitle], #p__linq__2)) OR (contains([Extent21].[Description], #p__linq__3)))
)) OR ( EXISTS (SELECT
1 AS [C1]
FROM [dbo].[EmployeeTags] AS [Extent22]
INNER JOIN (SELECT [Var_58].[Id] AS [Id], [Var_58].[Title] AS [Title]
FROM [dbo].[Tag] AS [Var_58]
WHERE ([Var_58].[IsDeleted] = #DynamicFilterParam_IsDeleted_IsDeleted) OR (#DynamicFilterParam_IsDeleted_DynamicFilterIsDisabled IS NOT NULL) ) AS [Extent23] ON [Extent23].[Id] = [Extent22].[FKTagId]
WHERE ([Extent13].[Id] = [Extent22].[FKEmployeeCvId]) AND (contains([Extent23].[Title], #p__linq__4))
))) AS [UnionAll1]
ORDER BY [UnionAll1].[Id] ASC, [UnionAll1].[Id1] ASC, [UnionAll1].[Id2] ASC, [UnionAll1].[Id3] ASC, [UnionAll1].[Id4] ASC, [UnionAll1].[Id5] ASC, [UnionAll1].[Id6] ASC, [UnionAll1].[C1] ASC',N'#DynamicFilterParam_IsDeleted_IsDeleted bit,#DynamicFilterParam_IsDeleted_DynamicFilterIsDisabled bit,#p__linq__0 char(4096),#p__linq__1 char(4096),#p__linq__2 char(4096),#p__linq__3 char(4096),#p__linq__4 char(4096)',#DynamicFilterParam_IsDeleted_IsDeleted=0,#DynamicFilterParam_IsDeleted_DynamicFilterIsDisabled=NULL,#p__linq__0='(sitecore)',#p__linq__1='(sitecore)',
#p__linq__2='(sitecore)',
#p__linq__3='(sitecore) ',#p__linq__4='(sitecore) '
When I am executing this query in the SQL MS it is giving me same error.
Even though I can successfully execute the contains query directly on the table like this:
select * from Employee where contains(FirstName,'"John*"')
This Linq works:
var employeeCV = _context.Employees.Where(x => x.FirstName.Contains(SearchQuery.Keyword)).ToList();
Your problem is that you are trying to run fulltext not on from Employees table, but on a Extent2, i.e. SELECT something FROM Employees WHERE ... and it is not full-text indexed. You will have to rewrite your linq query or do it in T-SQL instead of linq.
(SELECT [Var_42].[Id] AS [Id], [Var_42].[FirstName] AS [FirstName],
[Var_42].[Discriminator] AS [Discriminator]
FROM [dbo].[Employee] AS [Var_42]
WHERE ([Var_42].[IsDeleted] = #DynamicFilterParam_IsDeleted_IsDeleted) OR
(#DynamicFilterParam_IsDeleted_DynamicFilterIsDisabled IS NOT NULL) )
AS [Extent2]
I suggest that you try to rewrite your linq query like this:
ListOfEmployees = from cvs in _context.EmployeeCvs.Include(x => x.Employee)
where _Context.Employees.Any(
e=>e.FirstName.Contains(SearchQuery.Keyword)
&& e.EmployeeID == cvs.EmployeeID
))
... etc
This should generate a simple EXISTS statement which should work OK.
It is better to use query syntax, because you can name your subqueries.
The reason why EF is doing this "mess" for you is because you use Dynamic filters.
[Var_58].[IsDeleted] = #DynamicFilterParam_IsDeleted_IsDeleted
If you try to disable the Dynamic filters:
_context.DisableAllFilters();
it will not help you now, since it just sets the variable #DynamicFilterParam_IsDeleted_DynamicFilterIsDisabled in the generated query, but the query still will contain [Var_xx] subqueries, because EntityFramework.DynamicFilters overrides some methods of Entity Framework. See this link.
Why do dynamic filters cause problems?
The reason is mentioned here:
When I specify additional filters on entity queries (using linq's
.Where() clause, for example), those additional filters cause EF to
create sub-tables in the query.
So Dynamic filters create subqueries and there you get your exception, it is also well described here. There is a similar workaround recommended:
The workaround I'm currently using (which seems to work) is to always
force the Full Text Index predicate into a separate sub query so the
predicate is always executed against the base table rather than an
intermediate result set.
So you should try to convert all the conditions that are using full-text indexes to separate EXISTS statements.
It looks like you have to create a full-text index in your database first, if you're using MS SQL Server - see this link https://msdn.microsoft.com/en-us/library/ms187317.aspx if you want to do this via sql statements, otherwise see this link - https://technet.microsoft.com/en-us/library/aa197912(v=sql.80).aspx - if you want to do this via UI
Can you please confirm that you have full-text indexing enabled for ALL columns that participate in Contains function
select * from Employee where contains((FirstName,LastName),'"John*"')
select * from Tag where contains(Title,'"John*"')
I end up rewriting the LINQ like this to fix the problem:
var listOfEmployeeCV = from cvs in _context.EmployeeCvs.Include(x => x.Employee).Include(x=>x.Tags)
.Include(x=>x.ProjectExperiences)
where _context.Employees.Any(
e => e.FirstName.Contains(SearchQuery.Keyword)
&& e.Id == cvs.Employee.Id
) || (_context.Tags.Any(t=>t.Title.Contains(SearchQuery.Keyword) && cvs.Tags.Contains(t)))
|| (_context.ProjectExperiences.Any(pe=>(pe.ProjectTitle.Contains(SearchQuery.Keyword)
|| pe.Description.Contains(SearchQuery.Keyword)) &&
cvs.ProjectExperiences.Contains(pe)))
select new
EmployeeCvDTO
{
Employee = new EmployeeDTO
{
FirstName = cvs.Employee.FirstName,
LastName = cvs.Employee.LastName,
EnterpriseId = cvs.Employee.EnterpriseId,
Level = cvs.Employee.Level
//ProfileImageData = x.Employee.ProfileImageData
},
Tags = cvs.Tags,
ProjectExperiences = cvs.ProjectExperiences,
};
Use raw sql through Entity Framework, it works.
rtEntities rv = new rtEntities();
string query = string.Format("SELECT FT_TBL.ID, FT_TBL.Description, KEY_TBL.RANK FROM tbl_user AS FT_TBL INNER JOIN FREETEXTTABLE(tbl_user, Description, '(free text)', 5 ) AS KEY_TBL ON FT_TBL.ID = KEY_TBL.[KEY]");
var data = rv.Database.SqlQuery<userDetails>(query).ToList();
GridView1.DataSource = data;
GridView1.DataBind();

Is User.Identity.GetUserId cached or does it fetch from the database every time?

I'm using ASP.Net MVC 5 and I'm calling this line all over my code
string userId = User.Identity.GetUserId();
Does ASP.NET MVC go and fetch this from the table for each call, or does it get cached?
Looking at the decompiled sources of Microsoft.AspNet.Identity.Core.dll, you can see that it retrieves the user id from the claims of the current identity. So it doesn't fetch this info from the database.
public static string GetUserId(this IIdentity identity)
{
if (identity == null)
throw new ArgumentNullException("identity");
ClaimsIdentity identity1 = identity as ClaimsIdentity;
if (identity1 != null)
return IdentityExtensions.FindFirstValue(identity1, "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier");
return (string) null;
}
It seems that the id along with the username are cached when you login.
I've used SQL Server Profiler and after logged in running User.Identity.GetUserId(); the identity system made no queries to the database.
This is the query made on loggin:
exec sp_executesql N'SELECT
[UnionAll2].[C2] AS [C1],
[UnionAll2].[C3] AS [C2],
[UnionAll2].[C4] AS [C3],
[UnionAll2].[C5] AS [C4],
[UnionAll2].[C6] AS [C5],
[UnionAll2].[C7] AS [C6],
[UnionAll2].[C8] AS [C7],
[UnionAll2].[C9] AS [C8],
[UnionAll2].[C10] AS [C9],
[UnionAll2].[C11] AS [C10],
[UnionAll2].[C12] AS [C11],
[UnionAll2].[C13] AS [C12],
[UnionAll2].[C14] AS [C13],
[UnionAll2].[C1] AS [C14],
[UnionAll2].[C15] AS [C15],
[UnionAll2].[C16] AS [C16],
[UnionAll2].[C17] AS [C17],
[UnionAll2].[C18] AS [C18],
[UnionAll2].[C19] AS [C19],
[UnionAll2].[C20] AS [C20],
[UnionAll2].[C21] AS [C21],
[UnionAll2].[C22] AS [C22],
[UnionAll2].[C23] AS [C23],
[UnionAll2].[C24] AS [C24],
[UnionAll2].[C25] AS [C25]
FROM (SELECT
[UnionAll1].[C1] AS [C1],
[UnionAll1].[AccessFailedCount] AS [C2],
[UnionAll1].[Id] AS [C3],
[UnionAll1].[Email] AS [C4],
[UnionAll1].[EmailConfirmed] AS [C5],
[UnionAll1].[PasswordHash] AS [C6],
[UnionAll1].[SecurityStamp] AS [C7],
[UnionAll1].[PhoneNumber] AS [C8],
[UnionAll1].[PhoneNumberConfirmed] AS [C9],
[UnionAll1].[TwoFactorEnabled] AS [C10],
[UnionAll1].[LockoutEndDateUtc] AS [C11],
[UnionAll1].[LockoutEnabled] AS [C12],
[UnionAll1].[AccessFailedCount1] AS [C13],
[UnionAll1].[UserName] AS [C14],
[UnionAll1].[UserId] AS [C15],
[UnionAll1].[RoleId] AS [C16],
[UnionAll1].[UserId1] AS [C17],
[UnionAll1].[C2] AS [C18],
[UnionAll1].[C3] AS [C19],
[UnionAll1].[C4] AS [C20],
[UnionAll1].[C5] AS [C21],
[UnionAll1].[C6] AS [C22],
[UnionAll1].[C7] AS [C23],
[UnionAll1].[C8] AS [C24],
[UnionAll1].[C9] AS [C25]
FROM (SELECT
CASE WHEN ([Extent2].[UserId] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1],
[Limit1].[AccessFailedCount] AS [AccessFailedCount],
[Limit1].[Id] AS [Id],
[Limit1].[Email] AS [Email],
[Limit1].[EmailConfirmed] AS [EmailConfirmed],
[Limit1].[PasswordHash] AS [PasswordHash],
[Limit1].[SecurityStamp] AS [SecurityStamp],
[Limit1].[PhoneNumber] AS [PhoneNumber],
[Limit1].[PhoneNumberConfirmed] AS [PhoneNumberConfirmed],
[Limit1].[TwoFactorEnabled] AS [TwoFactorEnabled],
[Limit1].[LockoutEndDateUtc] AS [LockoutEndDateUtc],
[Limit1].[LockoutEnabled] AS [LockoutEnabled],
[Limit1].[AccessFailedCount] AS [AccessFailedCount1],
[Limit1].[UserName] AS [UserName],
[Extent2].[UserId] AS [UserId],
[Extent2].[RoleId] AS [RoleId],
[Extent2].[UserId] AS [UserId1],
CAST(NULL AS int) AS [C2],
CAST(NULL AS varchar(1)) AS [C3],
CAST(NULL AS varchar(1)) AS [C4],
CAST(NULL AS varchar(1)) AS [C5],
CAST(NULL AS varchar(1)) AS [C6],
CAST(NULL AS varchar(1)) AS [C7],
CAST(NULL AS varchar(1)) AS [C8],
CAST(NULL AS varchar(1)) AS [C9]
FROM (SELECT TOP (1)
[Extent1].[Id] AS [Id],
[Extent1].[Email] AS [Email],
[Extent1].[EmailConfirmed] AS [EmailConfirmed],
[Extent1].[PasswordHash] AS [PasswordHash],
[Extent1].[SecurityStamp] AS [SecurityStamp],
[Extent1].[PhoneNumber] AS [PhoneNumber],
[Extent1].[PhoneNumberConfirmed] AS [PhoneNumberConfirmed],
[Extent1].[TwoFactorEnabled] AS [TwoFactorEnabled],
[Extent1].[LockoutEndDateUtc] AS [LockoutEndDateUtc],
[Extent1].[LockoutEnabled] AS [LockoutEnabled],
[Extent1].[AccessFailedCount] AS [AccessFailedCount],
[Extent1].[UserName] AS [UserName]
FROM [dbo].[AspNetUsers] AS [Extent1]
WHERE [Extent1].[Id] = #p__linq__0 ) AS [Limit1]
LEFT OUTER JOIN [dbo].[AspNetUserRoles] AS [Extent2] ON [Limit1].[Id] = [Extent2].[UserId]
UNION ALL
SELECT
2 AS [C1],
[Limit2].[AccessFailedCount] AS [AccessFailedCount],
[Limit2].[Id] AS [Id],
[Limit2].[Email] AS [Email],
[Limit2].[EmailConfirmed] AS [EmailConfirmed],
[Limit2].[PasswordHash] AS [PasswordHash],
[Limit2].[SecurityStamp] AS [SecurityStamp],
[Limit2].[PhoneNumber] AS [PhoneNumber],
[Limit2].[PhoneNumberConfirmed] AS [PhoneNumberConfirmed],
[Limit2].[TwoFactorEnabled] AS [TwoFactorEnabled],
[Limit2].[LockoutEndDateUtc] AS [LockoutEndDateUtc],
[Limit2].[LockoutEnabled] AS [LockoutEnabled],
[Limit2].[AccessFailedCount] AS [AccessFailedCount1],
[Limit2].[UserName] AS [UserName],
CAST(NULL AS varchar(1)) AS [C2],
CAST(NULL AS varchar(1)) AS [C3],
CAST(NULL AS varchar(1)) AS [C4],
[Extent4].[Id] AS [Id1],
[Extent4].[UserId] AS [UserId],
[Extent4].[ClaimType] AS [ClaimType],
[Extent4].[ClaimValue] AS [ClaimValue],
CAST(NULL AS varchar(1)) AS [C5],
CAST(NULL AS varchar(1)) AS [C6],
CAST(NULL AS varchar(1)) AS [C7],
CAST(NULL AS varchar(1)) AS [C8]
FROM (SELECT TOP (1)
[Extent3].[Id] AS [Id],
[Extent3].[Email] AS [Email],
[Extent3].[EmailConfirmed] AS [EmailConfirmed],
[Extent3].[PasswordHash] AS [PasswordHash],
[Extent3].[SecurityStamp] AS [SecurityStamp],
[Extent3].[PhoneNumber] AS [PhoneNumber],
[Extent3].[PhoneNumberConfirmed] AS [PhoneNumberConfirmed],
[Extent3].[TwoFactorEnabled] AS [TwoFactorEnabled],
[Extent3].[LockoutEndDateUtc] AS [LockoutEndDateUtc],
[Extent3].[LockoutEnabled] AS [LockoutEnabled],
[Extent3].[AccessFailedCount] AS [AccessFailedCount],
[Extent3].[UserName] AS [UserName]
FROM [dbo].[AspNetUsers] AS [Extent3]
WHERE [Extent3].[Id] = #p__linq__0 ) AS [Limit2]
INNER JOIN [dbo].[AspNetUserClaims] AS [Extent4] ON [Limit2].[Id] = [Extent4].[UserId]) AS [UnionAll1]
UNION ALL
SELECT
3 AS [C1],
[Limit3].[AccessFailedCount] AS [AccessFailedCount],
[Limit3].[Id] AS [Id],
[Limit3].[Email] AS [Email],
[Limit3].[EmailConfirmed] AS [EmailConfirmed],
[Limit3].[PasswordHash] AS [PasswordHash],
[Limit3].[SecurityStamp] AS [SecurityStamp],
[Limit3].[PhoneNumber] AS [PhoneNumber],
[Limit3].[PhoneNumberConfirmed] AS [PhoneNumberConfirmed],
[Limit3].[TwoFactorEnabled] AS [TwoFactorEnabled],
[Limit3].[LockoutEndDateUtc] AS [LockoutEndDateUtc],
[Limit3].[LockoutEnabled] AS [LockoutEnabled],
[Limit3].[AccessFailedCount] AS [AccessFailedCount1],
[Limit3].[UserName] AS [UserName],
CAST(NULL AS varchar(1)) AS [C2],
CAST(NULL AS varchar(1)) AS [C3],
CAST(NULL AS varchar(1)) AS [C4],
CAST(NULL AS int) AS [C5],
CAST(NULL AS varchar(1)) AS [C6],
CAST(NULL AS varchar(1)) AS [C7],
CAST(NULL AS varchar(1)) AS [C8],
[Extent6].[LoginProvider] AS [LoginProvider],
[Extent6].[ProviderKey] AS [ProviderKey],
[Extent6].[UserId] AS [UserId],
[Extent6].[UserId] AS [UserId1]
FROM (SELECT TOP (1)
[Extent5].[Id] AS [Id],
[Extent5].[Email] AS [Email],
[Extent5].[EmailConfirmed] AS [EmailConfirmed],
[Extent5].[PasswordHash] AS [PasswordHash],
[Extent5].[SecurityStamp] AS [SecurityStamp],
[Extent5].[PhoneNumber] AS [PhoneNumber],
[Extent5].[PhoneNumberConfirmed] AS [PhoneNumberConfirmed],
[Extent5].[TwoFactorEnabled] AS [TwoFactorEnabled],
[Extent5].[LockoutEndDateUtc] AS [LockoutEndDateUtc],
[Extent5].[LockoutEnabled] AS [LockoutEnabled],
[Extent5].[AccessFailedCount] AS [AccessFailedCount],
[Extent5].[UserName] AS [UserName]
FROM [dbo].[AspNetUsers] AS [Extent5]
WHERE [Extent5].[Id] = #p__linq__0 ) AS [Limit3]
INNER JOIN [dbo].[AspNetUserLogins] AS [Extent6] ON [Limit3].[Id] = [Extent6].[UserId]) AS [UnionAll2]
ORDER BY [UnionAll2].[C3] ASC, [UnionAll2].[C1] ASC',N'#p__linq__0 nvarchar(4000)',#p__linq__0=N'b73f9738-76ed-48d5-a8fd-cbf23a233fe9'

Entity Framework, efficient NavigationProperty.OfType query

I'm having trouble constructing an efficient query in EF4 using type per table (TPT) inheritance.
I have an entity called Episode, and each episode can have multiple events. There several different type of events all deriving from a base entity called Event. I want to filter on all episodes that don't contain a certain type of event. Episode has a navigation property that is a collection of all its events (i.e. a collection of the base Event type)
I've tried:
from episode in context.EpisodeSet
where episode.Events.OfType<DerivedEvent>().Count() == 0
select episode
and
from episode in context.EpisodeSet
where episode.Events.Where(p => p is DerivedEvent).Count() == 0
select episode
Both of these produce a typical long SQL expansion that queries every Event type table.
Shouldn't there be a way to express this query in LINQ that just involves a join between the Episode and the DerivedEvent table in the resulting SQL?
Edit:
In response to ProfessorX here is the generated SQL (basically just a typical massive union across all event tables)
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[TypeId] AS [TypeId],
[Extent1].[PatientId] AS [PatientId],
[Extent1].[CentreId] AS [CentreId],
[Extent1].[CreatedOn] AS [CreatedOn],
[Extent1].[UpdatedOn] AS [UpdatedOn],
[Extent1].[CreatedBy] AS [CreatedBy],
[Extent1].[UpdatedBy] AS [UpdatedBy]
FROM [dbo].[Episode] AS [Extent1]
WHERE EXISTS (SELECT
1 AS [C1]
FROM [dbo].[Event] AS [Extent2]
LEFT OUTER JOIN (SELECT
[Extent3].[Id] AS [Id],
cast(1 as bit) AS [C1]
FROM [dbo].[InvasiveDischargableEvent] AS [Extent3] ) AS [Project1] ON [Extent2].[Id] = [Project1].[Id]
LEFT OUTER JOIN (SELECT
[UnionAll4].[C1] AS [C1],
[UnionAll4].[C2] AS [C2],
[UnionAll4].[C3] AS [C3],
[UnionAll4].[C4] AS [C4],
[UnionAll4].[C5] AS [C5],
[UnionAll4].[C6] AS [C6],
[UnionAll4].[C7] AS [C7]
FROM (SELECT
[UnionAll3].[C1] AS [C1],
[UnionAll3].[C2] AS [C2],
[UnionAll3].[C3] AS [C3],
[UnionAll3].[C4] AS [C4],
[UnionAll3].[C5] AS [C5],
[UnionAll3].[C6] AS [C6],
[UnionAll3].[C7] AS [C7]
FROM (SELECT
[UnionAll2].[C1] AS [C1],
[UnionAll2].[C2] AS [C2],
[UnionAll2].[C3] AS [C3],
[UnionAll2].[C4] AS [C4],
[UnionAll2].[C5] AS [C5],
[UnionAll2].[C6] AS [C6],
[UnionAll2].[C7] AS [C7]
FROM (SELECT
[UnionAll1].[Id] AS [C1],
[UnionAll1].[C1] AS [C2],
[UnionAll1].[C2] AS [C3],
[UnionAll1].[C3] AS [C4],
[UnionAll1].[C4] AS [C5],
[UnionAll1].[C5] AS [C6],
[UnionAll1].[C6] AS [C7]
FROM (SELECT
[Extent4].[Id] AS [Id],
cast(0 as bit) AS [C1],
cast(1 as bit) AS [C2],
cast(0 as bit) AS [C3],
cast(0 as bit) AS [C4],
cast(0 as bit) AS [C5],
cast(0 as bit) AS [C6]
FROM [dbo].[InvasivePSQ10Event] AS [Extent4]
UNION ALL
SELECT
[Extent5].[Id] AS [Id],
cast(0 as bit) AS [C1],
cast(0 as bit) AS [C2],
cast(0 as bit) AS [C3],
cast(0 as bit) AS [C4],
cast(0 as bit) AS [C5],
cast(1 as bit) AS [C6]
FROM [dbo].[InvasivePostTreatmentEvent] AS [Extent5]) AS [UnionAll1]
UNION ALL
SELECT
[Extent6].[Id] AS [Id],
cast(0 as bit) AS [C1],
cast(0 as bit) AS [C2],
cast(1 as bit) AS [C3],
cast(0 as bit) AS [C4],
cast(0 as bit) AS [C5],
cast(0 as bit) AS [C6]
FROM [dbo].[InvasiveTreatmentEvent] AS [Extent6]) AS [UnionAll2]
UNION ALL
SELECT
[Extent7].[Id] AS [Id],
cast(0 as bit) AS [C1],
cast(0 as bit) AS [C2],
cast(0 as bit) AS [C3],
cast(0 as bit) AS [C4],
cast(1 as bit) AS [C5],
cast(0 as bit) AS [C6]
FROM [dbo].[InvasiveConsultationEvent] AS [Extent7]) AS [UnionAll3]
UNION ALL
SELECT
[Extent8].[Id] AS [Id],
cast(1 as bit) AS [C1],
cast(0 as bit) AS [C2],
cast(0 as bit) AS [C3],
cast(0 as bit) AS [C4],
cast(0 as bit) AS [C5],
cast(0 as bit) AS [C6]
FROM [dbo].[InvasiveMOXFQEvent] AS [Extent8]) AS [UnionAll4]
UNION ALL
SELECT
[Extent9].[Id] AS [Id],
cast(0 as bit) AS [C1],
cast(0 as bit) AS [C2],
cast(0 as bit) AS [C3],
cast(1 as bit) AS [C4],
cast(0 as bit) AS [C5],
cast(0 as bit) AS [C6]
FROM [dbo].[InvasiveReferralEvent] AS [Extent9]) AS [UnionAll5] ON [Extent2].[Id] = [UnionAll5].[C1]
WHERE ([Extent1].[Id] = [Extent2].[EpisodeId]) AND (CASE WHEN (( NOT (([UnionAll5].[C2] = 1) AND ([UnionAll5].[C2] IS NOT NULL))) AND ( NOT (([UnionAll5].[C3] = 1) AND ([UnionAll5].[C3] IS NOT NULL))) AND ( NOT (([UnionAll5].[C4] = 1) AND ([UnionAll5].[C4] IS NOT NULL))) AND ( NOT (([Project1].[C1] = 1) AND ([Project1].[C1] IS NOT NULL))) AND ( NOT (([UnionAll5].[C5] = 1) AND ([UnionAll5].[C5] IS NOT NULL)))) THEN '2X' WHEN (([UnionAll5].[C5] = 1) AND ([UnionAll5].[C5] IS NOT NULL)) THEN '2X0X' WHEN (([Project1].[C1] = 1) AND ([Project1].[C1] IS NOT NULL) AND ( NOT (([UnionAll5].[C6] = 1) AND ([UnionAll5].[C6] IS NOT NULL))) AND ( NOT (([UnionAll5].[C7] = 1) AND ([UnionAll5].[C7] IS NOT NULL)))) THEN '2X1X' WHEN (([UnionAll5].[C4] = 1) AND ([UnionAll5].[C4] IS NOT NULL)) THEN '2X2X' WHEN (([UnionAll5].[C2] = 1) AND ([UnionAll5].[C2] IS NOT NULL)) THEN '2X3X' WHEN (([UnionAll5].[C6] = 1) AND ([UnionAll5].[C6] IS NOT NULL)) THEN '2X1X0X' WHEN (([UnionAll5].[C7] = 1) AND ([UnionAll5].[C7] IS NOT NULL)) THEN '2X1X1X' ELSE '2X4X' END LIKE '2X4X%')
)
After much head scratching I've managed to get this to work:
var episodes = (from episode in context.EpisodeSet
join e in context.EventSet.OfType<DerivedEvent>() on episode.Id equals e.EpisodeId into outer
from o in outer.DefaultIfEmpty()
where o == null
select episode)
So rather than try to apply an OfType filter to the navigation property I've had to apply it to the ObjectSet and do an outer join. Seems that OfType and 'as' type filtering don't work against Navigation Properties.
This produces the episodes that don't have a corresponding event in the DerivedEvent table, and with the kind of SQL that you would write by hand.
The LINQ follows the way you'd naturally write the query with SQL. It's just too easy to get seduced by all these navigation properties that lead to nice looking LINQ but awful looking SQL.
.Any() is better than .Count()
From my prospective your query can be optimized to:
context.EpisodeSet
.Where(e => e.Events.Any(p => p is DerivedEvent))
.Select(e => e);

Categories

Resources