When upgrading from preview5 to preview8 the following query throws
"The method or operation is not implemented."
The following query taken from:
https://github.com/KalikoCMS/KalikoCMS.NextGen/blob/netcore3.0-experimental/KalikoCMS.Legacy/Data/Repositories/LegacyContentRepository.cs#L35
var nodes = (from content in _context.Pages
join contentLanguage in _context.PageInstances.Where(x => x.DeletedDate == null && (x.Status == ContentStatus.Published || (x.Status == ContentStatus.WorkingCopy && x.CurrentVersion == 0)))
on content.PageId equals contentLanguage.PageId into grouped
orderby content.TreeLevel
select new ContentNode
{
ContentId = content.PageId,
SortOrder = content.SortOrder,
TreeLevel = content.TreeLevel,
ParentId = content.ParentId,
ContentTypeId = ToGuid(content.PageTypeId),
ContentProviderId = PageContentProvider.UniqueId,
Languages = (from contentLanguage in grouped
select new LanguageNode
{
ContentLanguageId = contentLanguage.PageInstanceId,
ContentName = contentLanguage.PageName,
ChildSortOrder = contentLanguage.ChildSortOrder,
StopPublish = contentLanguage.StopPublish,
UpdateDate = contentLanguage.UpdateDate,
ChildSortDirection = contentLanguage.ChildSortDirection,
Status = contentLanguage.Status,
Author = contentLanguage.Author,
StartPublish = contentLanguage.StartPublish,
CreatedDate = contentLanguage.CreatedDate,
VisibleInSitemap = contentLanguage.VisibleInSitemap,
CurrentVersion = contentLanguage.CurrentVersion,
UrlSegment = contentLanguage.PageUrl,
VisibleInMenu = contentLanguage.VisibleInMenu,
LanguageId = contentLanguage.LanguageId
}).ToList()
}).ToList();
It's saying that the GroupJoin can't be translated?
If I add .AsEnumerable to L35 then it works, because it's evaluating locally
I'm guessing the query needs to be rewritten, but not sure how it should look?
"The method or operation is not implemented."
Stack trace:
" at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateGroupJoin(ShapedQueryExpression outer, ShapedQueryExpression inner, LambdaExpression outerKeySelector, LambdaExpression innerKeySelector, LambdaExpression resultSelector)\r\n at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)\r\n at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)\r\n at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)\r\n at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)\r\n at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)\r\n at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)\r\n at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)\r\n at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)\r\n at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)\r\n at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query)\r\n at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](Expression query, Boolean async)\r\n at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async)\r\n at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass9_0`1.<Execute>b__0()\r\n at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func`1 compiler)\r\n at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)\r\n at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)\r\n at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)\r\n at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetEnumerator()\r\n at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)\r\n at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)\r\n at KalikoCMS.Legacy.Data.Repositories.LegacyContentRepository.GetContentNodes() in D:\\Programming\\Projects\\Libraries\\KalikoCMS.NextGen\\KalikoCMS.NextGen\\KalikoCMS.Legacy\\Data\\Repositories\\LegacyContentRepository.cs:line 35\r\n at KalikoCMS.Services.Content.ContentIndexService.Initialize() in D:\\Programming\\Projects\\Libraries\\KalikoCMS.NextGen\\KalikoCMS.NextGen\\KalikoCMS\\Services\\Content\\ContentIndexService.cs:line 30\r\n at KalikoCMS.Services.Initialization.InitializationService.Initialize() in D:\\Programming\\Projects\\Libraries\\KalikoCMS.NextGen\\KalikoCMS.NextGen\\KalikoCMS\\Services\\Initialization\\InitializationService.cs:line 45"
EF Core version: 3.0 preview8
Database Provider: Microsoft.EntityFrameworkCore.SqlServer
Operating system:
IDE: Visual Studio 2019 16.2 preview 2
Client side group join. This query cannot be translated to SQL directly. Adding AsEnumerable should be good way since it does not affect how much data is transferred from server.
Thanks for confirming, much appreciated.
Just for my understanding, this seems like a join that could be handled in the server.
There is no SQL equivalent of GroupJoin.
Cheers, thanks for clearing it up, makes sense.
I was thinking perhaps i could of used a navigational property instead to get around the issue.
I wonder how would I implement a left join in EF Core 3.0? As GroupJoin requires client-side evaluation and is disabled in 3.0, and Join is inner join, while the new LeftJoin is internal, currently I cannot figure out any approaches to perform a left join.
@coderfox - GroupJoin-DefaultIfEmpty-SelectMany is LINQ's way of writing Left join
e.g.
C#
from c in cs
join o in os on c.CustomerID equals o.CustomerID into grouping
from o in grouping.DefaultIfEmpty()
select { c, o }
This generates Customers LEFT JOIN Orders in database.
@smitpatel and that would translate obviously to client side evaluation? So you can't actually ever have a server side left join query?
@dotnetshadow - that would translate to
Select c.*, o.*
FROM Customers AS c
LEFT JOIN Orders AS o ON c.CustomerID = o.CustomerID
If you write a proper equivalent of LEFT JOIN on client side, we generate a left join. Not all variations of GroupJoin-DefaultIfEmpty-SelectMany are left join. LINQ has a lot more range variables in the scope than what LEFT JOIN could allow. So if you do it incorrectly, it is client evaluation. You can have server side left join query if you write it correctly. We have 100s of test verifying that.
Duplicate of #19930