How to convert LINQ nested Selectmany to SQL Regular Statements - c#

I know it's ain't gonna be easy but I'm stuck on this and can't move on.
I have this linq
var resourceItems = queryable
.Select(ri => new ResourceItemDto
{
Id = ri.Id,
CreationDate = ri.CreationDate,
ParentId = ri.FolderId,
Name = ri.Name,
Type = ri.ResourceType,
Url = ri.Url,
Size = ri.Size,
MediaAssetUuid = ri.MediaAssetUuid,
Blob = ri.Blob,
Container = ri.Container,
GroupId = ri.GroupId,
Status = (ResourceItemStatus) ri.Status,
Progress =
ri.EncodingJobs.SelectMany(j => j.EncodingTasks).Any()
? (ri.EncodingJobs.SelectMany(j => j.EncodingTasks).Sum(t => (decimal?) t.Progress)/
ri.EncodingJobs.SelectMany(j => j.EncodingTasks).Count() ?? 0M)
: 0M,
Uuid = ri.Uuid,
CreatedBy =
new UserDto
{
Id = ri.User.Id,
UserName = ri.User.UserName,
FirstName = ri.User.FirstName,
LastName = ri.User.LastName
}
});
And now the task is to move this into a SP and I don't want to take the sql generated by the EF, it's clumsy and machine-generated.
I ended up having this:
SELECT
ri.Id
,ri.CreationDate
,ri.FolderId
,ri.Name
,ri.ResourceType
,ri.Url
,ri.Size
,ri.MediaAssetUuid
,ri.Blob
,ri.Container
,ri.GroupId
--, (sql_expression) AS Progress
,ri.Uuid
,u.Id AS UserId
,u.UserName
,u.FirstName
,u.LastName
FROM ResourceItem ri
INNER JOIN ResourceItemsTree rit ON ri.FolderId = rit.Id
INNER JOIN [User] u ON u.Id = ri.CreatedBy
WHERE
ri.IsDeleted = CAST(0 as BIT)
Now my problem is that Progress column calculation which includes a few repeating SelectMany statements and I don't know how to do with this.
Any help is really appreciated, guys.
There's a EncodingJobs table having a FK ResourceItemId (0 to many) to the resourceItem table, and there's another table EncodingTask with a FK EncodingJobId (the same 0 to many).
This is what EF generates:
SELECT
[Project4].[Id] AS [Id],
[Project4].[CreationDate] AS [CreationDate],
[Project4].[FolderId] AS [FolderId],
[Project4].[Name] AS [Name],
[Project4].[ResourceType] AS [ResourceType],
[Project4].[Url] AS [Url],
[Project4].[Size] AS [Size],
[Project4].[MediaAssetUuid] AS [MediaAssetUuid],
[Project4].[Blob] AS [Blob],
[Project4].[Container] AS [Container],
[Project4].[GroupId] AS [GroupId],
[Project4].[Status] AS [Status],
CASE WHEN ( EXISTS (SELECT
1 AS [C1]
FROM [dbo].[EncodingJob] AS [Extent12]
INNER JOIN [dbo].[EncodingTask] AS [Extent13] ON [Extent12].[Id] = [Extent13].[JobId]
WHERE [Project4].[Id] = [Extent12].[ResourceItemId]
)) THEN CASE WHEN ([Project4].[C1] / CAST( [Project4].[C2] AS decimal(19,0)) IS NULL) THEN cast(0 as decimal(18)) ELSE [Project4].[C3] / CAST( [Project4].[C4] AS decimal(19,0)) END ELSE cast(0 as decimal(18)) END AS [C1],
[Project4].[Uuid] AS [Uuid],
[Project4].[CreatedBy] AS [CreatedBy],
[Project4].[UserName] AS [UserName],
[Project4].[FirstName] AS [FirstName],
[Project4].[LastName] AS [LastName]
FROM ( SELECT
[Project3].[Id] AS [Id],
[Project3].[FolderId] AS [FolderId],
[Project3].[Name] AS [Name],
[Project3].[ResourceType] AS [ResourceType],
[Project3].[Url] AS [Url],
[Project3].[Size] AS [Size],
[Project3].[MediaAssetUuid] AS [MediaAssetUuid],
[Project3].[Status] AS [Status],
[Project3].[CreationDate] AS [CreationDate],
[Project3].[GroupId] AS [GroupId],
[Project3].[Container] AS [Container],
[Project3].[Blob] AS [Blob],
[Project3].[Uuid] AS [Uuid],
[Project3].[CreatedBy] AS [CreatedBy],
[Project3].[UserName] AS [UserName],
[Project3].[FirstName] AS [FirstName],
[Project3].[LastName] AS [LastName],
[Project3].[C1] AS [C1],
[Project3].[C2] AS [C2],
[Project3].[C3] AS [C3],
(SELECT
COUNT(1) AS [A1]
FROM [dbo].[EncodingJob] AS [Extent10]
INNER JOIN [dbo].[EncodingTask] AS [Extent11] ON [Extent10].[Id] = [Extent11].[JobId]
WHERE [Project3].[Id] = [Extent10].[ResourceItemId]) AS [C4]
FROM ( SELECT
[Project2].[Id] AS [Id],
[Project2].[FolderId] AS [FolderId],
[Project2].[Name] AS [Name],
[Project2].[ResourceType] AS [ResourceType],
[Project2].[Url] AS [Url],
[Project2].[Size] AS [Size],
[Project2].[MediaAssetUuid] AS [MediaAssetUuid],
[Project2].[Status] AS [Status],
[Project2].[CreationDate] AS [CreationDate],
[Project2].[GroupId] AS [GroupId],
[Project2].[Container] AS [Container],
[Project2].[Blob] AS [Blob],
[Project2].[Uuid] AS [Uuid],
[Project2].[CreatedBy] AS [CreatedBy],
[Project2].[UserName] AS [UserName],
[Project2].[FirstName] AS [FirstName],
[Project2].[LastName] AS [LastName],
[Project2].[C1] AS [C1],
[Project2].[C2] AS [C2],
(SELECT
SUM([Extent9].[Progress]) AS [A1]
FROM [dbo].[EncodingJob] AS [Extent8]
INNER JOIN [dbo].[EncodingTask] AS [Extent9] ON [Extent8].[Id] = [Extent9].[JobId]
WHERE [Project2].[Id] = [Extent8].[ResourceItemId]) AS [C3]
FROM ( SELECT
[Project1].[Id] AS [Id],
[Project1].[FolderId] AS [FolderId],
[Project1].[Name] AS [Name],
[Project1].[ResourceType] AS [ResourceType],
[Project1].[Url] AS [Url],
[Project1].[Size] AS [Size],
[Project1].[MediaAssetUuid] AS [MediaAssetUuid],
[Project1].[Status] AS [Status],
[Project1].[CreationDate] AS [CreationDate],
[Project1].[GroupId] AS [GroupId],
[Project1].[Container] AS [Container],
[Project1].[Blob] AS [Blob],
[Project1].[Uuid] AS [Uuid],
[Project1].[CreatedBy] AS [CreatedBy],
[Project1].[UserName] AS [UserName],
[Project1].[FirstName] AS [FirstName],
[Project1].[LastName] AS [LastName],
[Project1].[C1] AS [C1],
(SELECT
COUNT(1) AS [A1]
FROM [dbo].[EncodingJob] AS [Extent6]
INNER JOIN [dbo].[EncodingTask] AS [Extent7] ON [Extent6].[Id] = [Extent7].[JobId]
WHERE [Project1].[Id] = [Extent6].[ResourceItemId]) AS [C2]
FROM ( SELECT
[Extent1].[Id] AS [Id],
[Extent1].[FolderId] AS [FolderId],
[Extent1].[Name] AS [Name],
[Extent1].[ResourceType] AS [ResourceType],
[Extent1].[Url] AS [Url],
[Extent1].[Size] AS [Size],
[Extent1].[MediaAssetUuid] AS [MediaAssetUuid],
[Extent1].[Status] AS [Status],
[Extent1].[CreationDate] AS [CreationDate],
[Extent1].[GroupId] AS [GroupId],
[Extent1].[Container] AS [Container],
[Extent1].[Blob] AS [Blob],
[Extent1].[Uuid] AS [Uuid],
[Extent1].[CreatedBy] AS [CreatedBy],
[Extent2].[UserName] AS [UserName],
[Extent3].[FirstName] AS [FirstName],
[Extent3].[LastName] AS [LastName],
(SELECT
SUM([Extent5].[Progress]) AS [A1]
FROM [dbo].[EncodingJob] AS [Extent4]
INNER JOIN [dbo].[EncodingTask] AS [Extent5] ON [Extent4].[Id] = [Extent5].[JobId]
WHERE [Extent1].[Id] = [Extent4].[ResourceItemId]) AS [C1]
FROM [dbo].[ResourceItem] AS [Extent1]
INNER JOIN [dbo].[User] AS [Extent2] ON [Extent1].[CreatedBy] = [Extent2].[Id]
LEFT OUTER JOIN [dbo].[User] AS [Extent3] ON [Extent1].[CreatedBy] = [Extent3].[Id]
WHERE ([Extent1].[IsDeleted] <> cast(1 as bit)) AND ([Extent1].[FolderId] = #p__linq__0)
) AS [Project1]
) AS [Project2]
) AS [Project3]
) AS [Project4]

you just need to think what you are looking for.
In this case its the total of the progress / count, grouped per resourceItem.
The following should be about right, but the IDs might need correcting!
This uses a common table expression (SQL Server) but could easily be rewritten to a subquery
;WITH prog AS
(
SELECT
ej.ResourceItemId,
SUM(et.Progress) / COUNT(*) AS totalProg
FROM EncodingJobs ej
JOIN EncodingTasks et ON ej.Id = et.EncodingJobId
GROUP BY
ej.ResourceItemId
)
SELECT
ri.Id
,ri.CreationDate
,ri.FolderId
,ri.Name
,ri.ResourceType
,ri.Url
,ri.Size
,ri.MediaAssetUuid
,ri.Blob
,ri.Container
,ri.GroupId
,ISNULL(prog.totalProg, 0) AS Progress
,ri.Uuid
,u.Id AS UserId
,u.UserName
,u.FirstName
,u.LastName
FROM ResourceItem ri
INNER JOIN ResourceItemsTree rit ON ri.FolderId = rit.Id
INNER JOIN [User] u ON u.Id = ri.CreatedBy
LEFT JOIN prog ON ri.Id = prog.ResourceItemId
WHERE
ri.IsDeleted = CAST(0 as BIT)

Well this should be something like that.
Cast the count to decimal if Progress is an integer, to avoid integer division.If not, you can avoid the cast
SELECT
ri.Id
,ri.CreationDate
,ri.FolderId
,ri.Name
,ri.ResourceType
,ri.Url
,ri.Size
,ri.MediaAssetUuid
,ri.Blob
,ri.Container
,ri.GroupId
coalesce(sum(et.Progress) / cast(count(*) as decimal(18,2)), 0) AS Progress
,ri.Uuid
,u.Id AS UserId
,u.UserName
,u.FirstName
,u.LastName
FROM ResourceItem ri
INNER JOIN ResourceItemsTree rit ON ri.FolderId = rit.Id
INNER JOIN [User] u ON u.Id = ri.CreatedBy
LEFT JOIN EncodingJob ej on ej.ResourceItemId= ri.Id
LEFT JOIN EncodingTask et on et.JobId = ej.Id
WHERE
ri.IsDeleted = 0
group by
ri.Id
,ri.CreationDate
,ri.FolderId
,ri.Name
,ri.ResourceType
,ri.Url
,ri.Size
,ri.MediaAssetUuid
,ri.Blob
,ri.Container
,ri.GroupId
,ri.Uuid
,u.Id AS UserId
,u.UserName
,u.FirstName
,u.LastName

You can attach SQL Server Profiler to my database and run the application. SQL Server Profiler will capture the SQL that is being run on the database. You can then use that SQL as a starting point for your stored procedure.
SQL Server Profiler Tutorial

Related

LINQ to SQL LEFT JOIN, GROUP BY, COUNT, MAX and subquery

I have 3 tables: Users, Roles, Bids.
Two of them is created by ASP.NET Identity, Bids is my custom table (it is secondary to Users table)
I'm trying to get all users that aren't in specific role (all non admin users) and show number of bids (they can be null - I have left join), show highest bid per user and show if that bid is max.
SQL query was quire easy:
SELECT
U.Id
,U.UserName
,U.Email
,ISNULL(MAX(B.PriceInPLN), 0)
,COUNT(B.BidID)
,IIF(MAX(B.PriceInPLN)=(SELECT TOP 1 PriceInPLN FROM Bids B2 (NOLOCK) ORDER BY PriceInPLN DESC),1,0 ) AS Max
FROM
AspNetUsers U ( NOLOCK )
JOIN AspNetUserRoles UR ( NOLOCK ) ON U.Id = UR.UserId
LEFT JOIN Bids B ( NOLOCK ) ON B.ApplicationUserId = U.Id
WHERE
UR.RoleId != '9508f9d2-12fb-4175-89a7-3275cb7616ae'
GROUP BY
U.Id
,U.UserName
,U.Email
But I have trouble creating correct LINQ query. Here is what I have so far:
var users =(
from u in db.Users
where !u.Roles.Select(r => r.RoleId).Contains(adminRoleId)//everyone except admins
join b in db.Bids on u equals b.ApplicationUser into ub
from subset in ub.DefaultIfEmpty()//LEFT JOIN
group subset by new { u.Id, u.UserName, u.Email, u.EmailConfirmed, u.Online } into grouped
select new UserReturnModel
{
Id = grouped.Key.Id,
Name = grouped.Key.UserName,
Email = grouped.Key.Email,
EmailConfirmed = grouped.Key.EmailConfirmed,
Online = grouped.Key.Online,
BidsCount = grouped.Count(c => c.ApplicationUserId == grouped.Key.Id),
PriceInPLN = grouped.Max(c => c.PriceInPLN),
IsMax = (grouped.Max(c=>c.PriceInPLN) == db.Bids.Max(b=>b.PriceInPLN))
}).ToList();
I can't get Max column to work correctly - it always says true.
Here are column definitions to easily show what I want to get:
Id = user id,
Name = user name,
Email = user email,
BidsCount = number of bids created by that user,
PriceInPLN = max price for that user,
IsMax = is this user offer highest comparing to other offers, if there are no offers this should be false
I'm using that in ASP.NET, when debugging I've noticed that SQL query created by LINQ is large:
SELECT
1 AS [C1],
[Project6].[Id] AS [Id],
[Project6].[UserName] AS [UserName],
[Project6].[Email] AS [Email],
[Project6].[EmailConfirmed] AS [EmailConfirmed],
[Project6].[Online] AS [Online],
[Project6].[C4] AS [C2],
[Project6].[C1] AS [C3],
CASE WHEN (([Project6].[C2] = [GroupBy3].[A1]) OR (([Project6].[C2] IS NULL) AND ([GroupBy3].[A1] IS NULL))) THEN cast(1 as bit) WHEN ( NOT (([Project6].[C3] = [GroupBy4].[A1]) AND ((CASE WHEN ([Project6].[C3] IS NULL) THEN cast(1 as bit) ELSE cast(0 as bit) END) = (CASE WHEN ([GroupBy4].[A1] IS NULL) THEN cast(1 as bit) ELSE cast(0 as bit) END)))) THEN cast(0 as bit) END AS [C4]
FROM (SELECT
[Project3].[C1] AS [C1],
[Project3].[C2] AS [C2],
[Project3].[C3] AS [C3],
[Project3].[Id] AS [Id],
[Project3].[Online] AS [Online],
[Project3].[Email] AS [Email],
[Project3].[EmailConfirmed] AS [EmailConfirmed],
[Project3].[UserName] AS [UserName],
(SELECT
COUNT(1) AS [A1]
FROM ( SELECT
[Extent4].[Id] AS [Id],
[Extent4].[Online] AS [Online],
[Extent4].[Email] AS [Email],
[Extent4].[EmailConfirmed] AS [EmailConfirmed],
[Extent4].[UserName] AS [UserName],
[Extent5].[ApplicationUserId] AS [ApplicationUserId]
FROM [dbo].[AspNetUsers] AS [Extent4]
INNER JOIN [dbo].[Bids] AS [Extent5] ON [Extent5].[ApplicationUserId] = [Extent4].[Id]
WHERE ( NOT EXISTS (SELECT
1 AS [C1]
FROM [dbo].[AspNetUserRoles] AS [Extent6]
WHERE ([Extent4].[Id] = [Extent6].[UserId]) AND ([Extent6].[RoleId] = #p__linq__0)
)) AND ([Project3].[Id] = [Extent4].[Id]) AND ([Project3].[UserName] = [Extent4].[UserName]) AND (([Project3].[Email] = [Extent4].[Email]) OR (([Project3].[Email] IS NULL) AND ([Extent4].[Email] IS NULL))) AND ([Project3].[EmailConfirmed] = [Extent4].[EmailConfirmed]) AND ([Project3].[Online] = [Extent4].[Online]) AND ([Extent5].[ApplicationUserId] = [Project3].[Id])
) AS [Project5]) AS [C4]
FROM ( SELECT
[GroupBy1].[A1] AS [C1],
[GroupBy1].[A2] AS [C2],
[GroupBy1].[A3] AS [C3],
[GroupBy1].[K1] AS [Id],
[GroupBy1].[K2] AS [Online],
[GroupBy1].[K3] AS [Email],
[GroupBy1].[K4] AS [EmailConfirmed],
[GroupBy1].[K5] AS [UserName]
FROM ( SELECT
[Project2].[Id] AS [K1],
[Project2].[Online] AS [K2],
[Project2].[Email] AS [K3],
[Project2].[EmailConfirmed] AS [K4],
[Project2].[UserName] AS [K5],
MAX([Project2].[PriceInPLN]) AS [A1],
MAX([Project2].[PriceInPLN]) AS [A2],
MAX([Project2].[PriceInPLN]) AS [A3]
FROM ( SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Online] AS [Online],
[Extent1].[Email] AS [Email],
[Extent1].[EmailConfirmed] AS [EmailConfirmed],
[Extent1].[UserName] AS [UserName],
[Extent2].[PriceInPLN] AS [PriceInPLN],
[Extent2].[ApplicationUserId] AS [ApplicationUserId]
FROM [dbo].[AspNetUsers] AS [Extent1]
LEFT OUTER JOIN [dbo].[Bids] AS [Extent2] ON [Extent1].[Id] = [Extent2].[ApplicationUserId]
WHERE NOT EXISTS (SELECT
1 AS [C1]
FROM [dbo].[AspNetUserRoles] AS [Extent3]
WHERE ([Extent1].[Id] = [Extent3].[UserId]) AND ([Extent3].[RoleId] = #p__linq__0)
)
) AS [Project2]
GROUP BY [Project2].[Id], [Project2].[Online], [Project2].[Email], [Project2].[EmailConfirmed], [Project2].[UserName]
) AS [GroupBy1]
) AS [Project3] ) AS [Project6]
CROSS JOIN (SELECT
MAX([Extent7].[PriceInPLN]) AS [A1]
FROM [dbo].[Bids] AS [Extent7] ) AS [GroupBy3]
CROSS JOIN (SELECT
MAX([Extent8].[PriceInPLN]) AS [A1]
FROM [dbo].[Bids] AS [Extent8] ) AS [GroupBy4]
Can this be simplified?
Here is model of my my database generated by Entity Framework Power Tools:
I'm not sure why you modified your LINQ query so much from the original SQL query, but translating the SQL query closer to literally using the rules from my SQL to LINQ Recipe I get
var MaxPriceInPLN = db.Bids.Max(b => b.PriceInPLN);
var ans = from U in db.Users
where !U.Roles.Any(r => r.RoleId == adminRoleId)
join b in db.Bids on U.Id equals b.ApplicationUserId into bj
from b in bj.DefaultIfEmpty()
group new { U, b } by new { U.Id, U.UserName, U.Email } into Ubg
let maxBidPriceInPLN = Ubg.Max(Ub => Ub.b.PriceInPLN)
select new {
Ubg.Key.Id,
Ubg.Key.UserName,
Ubg.Key.Email,
PriceInPLN = maxBidPriceInPLN ?? 0,
BidsCount = Ubg.Count(Ub => Ub.b != null),
IsMax = maxBidPriceInPLN == MaxPriceInPLN
};
You can simplify the LINQ query by using the EF navigation properties to hide the join from your query:
var MaxPriceInPLN = db.Bids.Max(b => b.PriceInPLN);
var ans = from U in db.Users
where !U.Roles.Any(r => r.RoleId == adminRoleId)
let maxBidPriceInPLN = U.Bids.Max(b => b.PriceInPLN)
select new {
U.Id,
U.UserName,
U.Email,
PriceInPLN = maxBidPriceInPLN ?? 0,
BidsCount = U.Bids.Count(),
IsMax = maxBidPriceInPLN == MaxPriceInPLN
};

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.

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();

Entity Framework Include returning different values for Single and Where

My application can be used to send messages to a combination of single users and teams containing sets of users. The structure is such, that a Message entity has one Recipients entity, which in turn has a list of User entities and a list of Team entities.
I am trying to get a list of Message entities using EF Code First and Linq-to-Entities, and I want to Include the Recipients and Teams to avoid large amounts of lazy loading requests later on.
The strange thing is, the Teams list is always empty if I use the Include clause. After some experimenting, it boils down to this:
var messages = GetAll()
.Include(m => m.Recipients.Teams)
.Where(m => m.Id == 123)
.ToList();
returns a list with one message, where the Teams list is empty. (GetAll() just returns an IQueryable<Message>.) But if I do
var message = GetAll()
.Include(m => m.Recipients.Teams)
.Single(m => m.Id == 123);
then I get the single message, with the Teams correctly populated.
Any ideas why this is happening?
Edit: Here's the generated SQL (taken from Entity Framework Profiler)
Where statement
SELECT *
FROM (SELECT [Extent1].[Id] AS [Id],
[Extent1].[ParentRelation] AS [ParentRelation],
[Extent1].[CreatedUtc] AS [CreatedUtc],
[Extent1].[Subject] AS [Subject],
[Extent1].[Introduction] AS [Introduction],
[Extent1].[Body] AS [Body],
[Extent1].[GlobalId] AS [GlobalId],
[Extent1].[Team_Id] AS [Team_Id],
[Extent1].[Creator_Id] AS [Creator_Id],
[Extent1].[Parent_Id] AS [Parent_Id],
[Extent1].[ReplyTo_Id] AS [ReplyTo_Id],
[Join1].[Id1] AS [Id1],
[Join1].[ToSupervisors] AS [ToSupervisors],
[Join1].[Organisation_Id] AS [Organisation_Id],
[Join1].[Id2] AS [Id2],
[Join4].[Id3] AS [Id3],
[Join4].[Name] AS [Name],
[Join4].[CreatedUtc] AS [CreatedUtc1],
[Join4].[Description] AS [Description],
[Join4].[Color] AS [Color],
[Join4].[Status] AS [Status],
[Join4].[Organisation_Id] AS [Organisation_Id1],
CASE
WHEN ([Join4].[Recipients_Id1] IS NULL) THEN CAST(NULL AS int)
ELSE 1
END AS [C1]
FROM [dbo].[Messages] AS [Extent1]
INNER JOIN (SELECT [Extent2].[Id] AS [Id1],
[Extent2].[ToSupervisors] AS [ToSupervisors],
[Extent2].[Organisation_Id] AS [Organisation_Id],
[Extent3].[Id] AS [Id2]
FROM [dbo].[Recipients] AS [Extent2]
LEFT OUTER JOIN [dbo].[MessageExtensions] AS [Extent3]
ON [Extent2].[Id] = [Extent3].[Recipients_Id]) AS [Join1]
ON [Extent1].[Recipients_Id] = [Join1].[Id1]
LEFT OUTER JOIN (SELECT [Extent4].[Recipients_Id] AS [Recipients_Id1],
[Extent5].[Id] AS [Id3],
[Extent5].[Name] AS [Name],
[Extent5].[CreatedUtc] AS [CreatedUtc],
[Extent5].[Description] AS [Description],
[Extent5].[Color] AS [Color],
[Extent5].[Status] AS [Status],
[Extent5].[Organisation_Id] AS [Organisation_Id],
[Extent6].[Recipients_Id] AS [Recipients_Id2]
FROM [dbo].[RecipientsTeams] AS [Extent4]
INNER JOIN [dbo].[Teams] AS [Extent5]
ON [Extent4].[Team_Id] = [Extent5].[Id]
INNER JOIN [dbo].[MessageExtensions] AS [Extent6]
ON 1 = 1) AS [Join4]
ON ([Extent1].[Recipients_Id] = [Join4].[Recipients_Id2])
AND ([Extent1].[Recipients_Id] = [Join4].[Recipients_Id1])
WHERE 11021 = [Extent1].[Id]) AS [Project1]
ORDER BY [Project1].[Id] ASC,
[Project1].[Id1] ASC,
[Project1].[Id2] ASC,
[Project1].[C1] ASC
Single statement
SELECT *
FROM (SELECT [Limit1].[Id1] AS [Id],
[Limit1].[ParentRelation] AS [ParentRelation],
[Limit1].[CreatedUtc] AS [CreatedUtc],
[Limit1].[Subject] AS [Subject],
[Limit1].[Introduction] AS [Introduction],
[Limit1].[Body1] AS [Body],
[Limit1].[GlobalId1] AS [GlobalId],
[Limit1].[Team_Id] AS [Team_Id],
[Limit1].[Creator_Id] AS [Creator_Id],
[Limit1].[Parent_Id] AS [Parent_Id],
[Limit1].[ReplyTo_Id] AS [ReplyTo_Id],
[Limit1].[Id2] AS [Id1],
[Limit1].[ToSupervisors] AS [ToSupervisors],
[Limit1].[Organisation_Id] AS [Organisation_Id],
[Limit1].[Id3] AS [Id2],
[Join5].[Id4] AS [Id3],
[Join5].[Name] AS [Name],
[Join5].[CreatedUtc1] AS [CreatedUtc1],
[Join5].[Description] AS [Description],
[Join5].[Color] AS [Color],
[Join5].[Status] AS [Status],
[Join5].[Organisation_Id] AS [Organisation_Id1],
CASE
WHEN ([Join5].[Recipients_Id1] IS NULL) THEN CAST(NULL AS int)
ELSE 1
END AS [C1]
FROM (SELECT TOP (2) [Extent1].[Id] AS [Id1],
[Extent1].[ParentRelation] AS [ParentRelation],
[Extent1].[CreatedUtc] AS [CreatedUtc],
[Extent1].[Subject] AS [Subject],
[Extent1].[Introduction] AS [Introduction],
[Extent1].[Body] AS [Body1],
[Extent1].[GlobalId] AS [GlobalId1],
[Extent1].[Team_Id] AS [Team_Id],
[Extent1].[Creator_Id] AS [Creator_Id],
[Extent1].[Parent_Id] AS [Parent_Id],
[Extent1].[ReplyTo_Id] AS [ReplyTo_Id],
[Join1].[Id2],
[Join1].[ToSupervisors],
[Join1].[Organisation_Id],
[Join1].[Id3]
FROM [dbo].[Messages] AS [Extent1]
INNER JOIN (SELECT [Extent2].[Id] AS [Id2],
[Extent2].[ToSupervisors] AS [ToSupervisors],
[Extent2].[Organisation_Id] AS [Organisation_Id],
[Extent3].[Id] AS [Id3]
FROM [dbo].[Recipients] AS [Extent2]
LEFT OUTER JOIN [dbo].[MessageExtensions] AS [Extent3]
ON [Extent2].[Id] = [Extent3].[Recipients_Id]) AS [Join1]
ON [Extent1].[Recipients_Id] = [Join1].[Id2]
WHERE 11021 = [Extent1].[Id]) AS [Limit1]
LEFT OUTER JOIN (SELECT [Extent4].[Recipients_Id] AS [Recipients_Id1],
[Extent5].[Id] AS [Id4],
[Extent5].[Name] AS [Name],
[Extent5].[CreatedUtc] AS [CreatedUtc1],
[Extent5].[Description] AS [Description],
[Extent5].[Color] AS [Color],
[Extent5].[Status] AS [Status],
[Extent5].[Organisation_Id] AS [Organisation_Id],
[Join4].[Id5],
[Join4].[Recipients_Id2]
FROM [dbo].[RecipientsTeams] AS [Extent4]
INNER JOIN [dbo].[Teams] AS [Extent5]
ON [Extent4].[Team_Id] = [Extent5].[Id]
INNER JOIN (SELECT [Extent6].[Id] AS [Id5],
[Extent6].[Recipients_Id] AS [Recipients_Id2]
FROM [dbo].[Messages] AS [Extent6]
LEFT OUTER JOIN [dbo].[MessageExtensions] AS [Extent7]
ON [Extent6].[Recipients_Id] = [Extent7].[Recipients_Id]) AS [Join4]
ON [Extent4].[Recipients_Id] = [Join4].[Recipients_Id2]) AS [Join5]
ON [Limit1].[Id1] = [Join5].[Id5]) AS [Project1]
ORDER BY [Project1].[Id] ASC,
[Project1].[Id1] ASC,
[Project1].[Id2] ASC,
[Project1].[C1] ASC
When I run these queries by hand, I have the same result. For the Where, the Team related properties are all NULL, while for the Single, they are populated.
Edit 2 The GetAll method is a repository method
public virtual IQueryable<T> GetAll()
{
return Context.Set<T>();
}
where T is Message
Can you try this?
var messages = GetAll().Include(m => m.Recipients.Teams) .Where(m => m.Id == 123).Select(m=>m);

How to group by int null values in IQueryable LINQ

I have a list of StudentGrades which contains TermNumber, I want to group them by TermNumber. However, when I look at the results, the ones with null TermNumbers are not returned/grouped.
IQueryable<StudentGradeDm> query = GetListQuery().Where(m => m.StudentId == studentId);
IQueryable<StudentGradeDto> groupedQuery = query.GroupBy(m => m.TermNumber)
.Select(m => new StudentGradeDto
{
TermNumber = m.Key,
StudentGrades = m.ToList()
});
return groupedQuery;
As you can see from the lovely screenshot i've taken here .. there are 3 groups, however, the first group is null because their TermNumber is null. But theoretically, who cares if its null? The StudentGrades with null TermNumber should still be a group.
I understand that one fix to this would be to call
query.ToList().GroupBy ......
But this is not an option for me, as the streamlined application will take a query such as the one above, and feed it into a generic pagination and sort function, in which only a subset of records will be fetched from the database to improve performance.
Any expert inputs would be greatly appreciated!
Update: Here is the generated SQL
{SELECT
[Project2].[C2] AS [C1],
[Project2].[C1] AS [C2],
[Project2].[C3] AS [C3],
[Project2].[Id] AS [Id],
[Project2].[StudentId] AS [StudentId],
[Project2].[Year] AS [Year],
[Project2].[TermTypeId] AS [TermTypeId],
[Project2].[TermNumber] AS [TermNumber],
[Project2].[ClassId] AS [ClassId],
[Project2].[GradeId] AS [GradeId],
[Project2].[FileId] AS [FileId],
[Project2].[CreatedById] AS [CreatedById],
[Project2].[CreatedDate] AS [CreatedDate],
[Project2].[ModifiedById] AS [ModifiedById],
[Project2].[ModifiedDate] AS [ModifiedDate],
[Project2].[Deleted] AS [Deleted]
FROM ( SELECT
[Distinct1].[C1] AS [C1],
1 AS [C2],
[Extent2].[Id] AS [Id],
[Extent2].[StudentId] AS [StudentId],
[Extent2].[Year] AS [Year],
[Extent2].[TermTypeId] AS [TermTypeId],
[Extent2].[TermNumber] AS [TermNumber],
[Extent2].[ClassId] AS [ClassId],
[Extent2].[GradeId] AS [GradeId],
[Extent2].[FileId] AS [FileId],
[Extent2].[CreatedById] AS [CreatedById],
[Extent2].[CreatedDate] AS [CreatedDate],
[Extent2].[ModifiedById] AS [ModifiedById],
[Extent2].[ModifiedDate] AS [ModifiedDate],
[Extent2].[Deleted] AS [Deleted],
CASE WHEN ([Extent2].[Id] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C3]
FROM (SELECT DISTINCT
[Extent1].[TermNumber] AS [C1]
FROM [dbo].[StudentGrade] AS [Extent1]
WHERE ([Extent1].[Deleted] <> 1) AND ([Extent1].[StudentId] = #p__linq__0) ) AS [Distinct1]
LEFT OUTER JOIN [dbo].[StudentGrade] AS [Extent2] ON ([Extent2].[Deleted] <> 1) AND ([Extent2].[StudentId] = #p__linq__0) AND ([Distinct1].[C1] = [Extent2].[TermNumber])
) AS [Project2]
ORDER BY [Project2].[C1] ASC, [Project2].[C3] ASC}

Categories

Resources