简体   繁体   English

无法翻译 LINQ 表达式。 以可翻译的形式重写查询,或切换到客户端评估 EF Core 3.1

[英]The LINQ expression could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation EF Core 3.1

I'm struggling with this for four days already and no progress at all.我已经为此苦苦挣扎了四天,但根本没有任何进展。 Having a query, which worked just fine before updating to EF Core 3.1:有一个查询,在更新到 EF Core 3.1 之前运行良好:

var equipments = await this.DbContext.ServContrObjStructEquipment
            .AsNoTracking()
            .Where(e => e.ServContrObjStruct.ServContrObjStructParent.ServContrObjStructParent.Objectuuid == sectionGuid)
            .Where(e => e.ServContrObjStructPlanEquipment.Select(x => x.PkServContrObjStructPlanEquipment).Contains(
                e.ServContrObjStructPlanEquipment.OrderByDescending(x => x.ServContrObjStructPlanVers.ActiveUntil ?? DateTime.MaxValue).ThenByDescending(x => x.ServContrObjStructPlanVers.ActiveFrom).ThenByDescending(x => x.ActiveFrom).Select(x => x.PkServContrObjStructPlanEquipment).FirstOrDefault()
                ))

Now it throws me an Exception that says:现在它向我抛出一个异常,上面写着:

The LINQ expression 'DbSet .Where(s3 => s3.RecStatus == 1) .Where(s3 => EF.Property>((EntityShaperExpression: EntityType: ServContrObjStructEquipment ValueBufferExpression: (ProjectionBindingExpression: Outer.Outer.Outer) IsNullable: False ), "PkServContrObjStructEquipment") != null && EF.Property>((EntityShaperExpression: EntityType: ServContrObjStructEquipment ValueBufferExpression: (ProjectionBindingExpression: Outer.Outer.Outer) IsNullable: False ), "PkServContrObjStructEquipment") == EF.Property>(s3, "FkServContrObjStructEquipment")) .Select(s3 => s3.PkServContrObjStructPlanEquipment) .Contains((MaterializeCollectionNavigation( navigation: Navigation: ServContrObjStructEquipment.ServContrObjStructPlanEquipment, subquery: DbSet .Where(s4 => s4.RecStatus == 1) .Where(i => EF.Property>((EntityShaperExpression: EntityType: ServContrObjStructEquipment ValueBufferExpression: (ProjectionBindingExpression: Outer.Outer.Outer) IsNullable: False ), "PkServContrObjStructEquipment") != null && LINQ 表达式 'DbSet .Where(s3 => s3.RecStatus == 1) .Where(s3 => EF.Property>((EntityShaperExpression: EntityType: ServContrObjStructEquipment ValueBufferExpression: (ProjectionBindingExpression: Outer.Outer.Outer) IsFalseNullable) , "PkServContrObjStructEquipment") != null && EF.Property>((EntityShaperExpression: EntityType: ServContrObjStructEquipment ValueBufferExpression: (ProjectionBindingExpression: Outer.Outer.Outer) IsNullable: False ), "PkServUCStruct3", ==. FkServContrObjStructEquipment")) .Select(s3 => s3.PkServContrObjStructPlanEquipment) .Contains((MaterializeCollectionNavigation( 导航:导航:ServContrObjStructEquipment.ServContrObjStructPlanEquipment => s3.PkServContrObjStructPlanEquipment)。 EF.Property>((EntityShaperExpression: EntityType: ServContrObjStructEquipment ValueBufferExpression: (ProjectionBindingExpression: Outer.Outer.Outer) IsNullable: False ), "PkServContrObjStructEquipment") != null && EF.Property>((EntityShaperExpression: EntityType: ServContrObjStructEquipment ValueBufferExpression: (ProjectionBindingExpression: Outer.Outer.Outer) IsNullable: False ), "PkServContrObjStructEquipment") == EF.Property>(i, "FkServContrObjStructEquipment"))) .AsQueryable() .OrderByDescending(x => x.ServContrObjStructPlanVers.ActiveUntil ?? EF.Property>((EntityShaperExpression: EntityType: ServContrObjStructEquipment ValueBufferExpression: (ProjectionBindingExpression: Outer.Outer.Outer) IsNullable: False ), "PkServContrObjStructEquipment") == EF.Property>(i, "Equib.Fk"Struct)Servable) .OrderByDescending(x => x.ServContrObjStructPlanVers.ActiveUntil ?? 12/31/9999 11:59:59 PM) .ThenByDescending(x => x.ServContrObjStructPlanVers.ActiveFrom) .ThenByDescending(x => x.ActiveFrom) .Select(x => x.PkServContrObjStructPlanEquipment) .FirstOrDefault())' could not be translated. 12/31/9999 11:59:59 PM) .ThenByDescending(x => x.ServContrObjStructPlanVers.ActiveFrom) .ThenByDescending(x => x.ActiveFrom) .Select(x => x.PkServContrObjStructPlanEquipment()) .First无法翻译。 Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync().以可翻译的形式重写查询,或通过插入对 AsEnumerable()、AsAsyncEnumerable()、ToList() 或 ToListAsync() 的调用显式切换到客户端评估。 See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.有关详细信息,请参阅https://go.microsoft.com/fwlink/?linkid=2101038

I am aware about EF Core 3.0-3.1 has breaking changes and that client evaluation is now performed on the top level Select() .我知道 EF Core 3.0-3.1 有重大更改,并且客户端评估现在在顶级Select() Although I'd rather avoid doing that, I've tried calling all the ToList() , AsEnumerable() etc. to make it work, but it also doesn't help: the query is complex and multilevel, so calling ToList() at any point either breaks it or does not get related records (because of the Lazy loading I guess) which are then needed for further execution of the query.虽然我宁愿避免这样做,但我已经尝试调用所有ToList()AsEnumerable()等以使其工作,但这也无济于事:查询很复杂且多级,因此调用ToList()在任何时候要么破坏它,要么没有获得相关记录(因为我猜是延迟加载),然后需要进一步执行查询。

I've also tried splitting the query into separate queries to see what's going on there like this:我还尝试将查询拆分为单独的查询,以查看那里发生了什么,如下所示:

var intermEquipments = await this.DbContext.ServContrObjStructEquipment
                .AsNoTracking()
                .Include(e => e.ServContrObjStructPlanEquipment)
             .Where(e=>e.ServContrObjStruct.ServContrObjStructParent.ServContrObjStructParent.Objectuuid == sectionGuid)
                .ToListAsync();

            var intermEquipments1 = await this.DbContext.ServContrObjStructEquipment
                .AsNoTracking()
                .Include(e => e.ServContrObjStructPlanEquipment)
                .Where(e => e.ServContrObjStruct.ServContrObjStructParent.ServContrObjStructParent.Objectuuid == sectionGuid)
                .Select(e => e.ServContrObjStructPlanEquipment.Select(x => x.PkServContrObjStructPlanEquipment))
                .ToListAsync();

            var intermEquipments2 = this.DbContext.ServContrObjStructEquipment
                .AsNoTracking()
                .Include(e => e.ServContrObjStructPlanEquipment)
                .Where(e => e.ServContrObjStruct.ServContrObjStructParent.ServContrObjStructParent.Objectuuid == sectionGuid)
                .Select(e => e.ServContrObjStructPlanEquipment
                    .OrderByDescending(x => x.ServContrObjStructPlanVers.ActiveUntil ?? DateTime.MaxValue)
                                .ThenByDescending(x => x.ServContrObjStructPlanVers.ActiveFrom)
                                    .ThenByDescending(x => x.ActiveFrom)
                                        .Select(x => x.PkServContrObjStructPlanEquipment).ToList());

but it either throws me an Exception saying that但它要么给我抛出一个异常,说

Lambda expression used inside Include is not valid Include 中使用的 Lambda 表达式无效

or NullReference (because some related properties are not loaded, as I mentioned above) or not showing the records at all.或者 NullReference(因为一些相关的属性没有加载,正如我上面提到的)或者根本不显示记录。

I am familiar with EntityFramework, though I'm not an expert.我熟悉 EntityFramework,虽然我不是专家。 Is there a way to rewrite this query so it can be translated or just do anything to make it work?有没有办法重写这个查询,以便它可以被翻译或只是做任何事情来使它工作? Thank you!谢谢!

This looks to be a bug or some kind of breaking change in EF Core (surprise surprise).这看起来是 EF Core 中的一个错误或某种重大更改(惊喜)。 At first I suspected the use of DateTime.MaxValue as EF Core had issues with that in the past, but it's not that.起初我怀疑使用 DateTime.MaxValue 作为 EF Core 过去有问题,但事实并非如此。 It is taking exception to doing the OrderBy sub-select inside the Contains for some reason.由于某种原因,在Contains 中执行OrderBy 子选择是不正常的。 One breaking change of EF Core 3 from 2.2.6 was that Core 2 would automatically switch to client-side expressions where Core will throw an exception however I was able to confirm with a Profiler that a query like this was successfully translated to SQL with Core 2.2.6 but in 3.1 it does not translate resulting in the error.从 2.2.6 开始,EF Core 3 的一个重大变化是 Core 2 会自动切换到客户端表达式,其中 Core 将抛出异常,但是我能够使用 Profiler 确认这样的查询已成功转换为带有 Core 的 SQL 2.2.6 但在 3.1 它不翻译导致错误。 At this point you could raise a bug report with the EF Core team.此时,您可以向 EF Core 团队提交错误报告。

I was able to reproduce this with a simpler query:我能够用一个更简单的查询重现这个:

var results = context.Parents.Where(x => x.Children.Select(c => c.ChildId)
   .Contains(x.Children.OrderByDescending(c => c.BirthDate).Select(c => c.ChildId).FirstOrDefault()))
   .ToList();

Run in 2.2.6 it compiles successfully to SQL.在 2.2.6 中运行它成功编译为 SQL。 3.1 chucks an exception. 3.1 卡盘例外。

It would probably be beneficial to understand exactly what this query is meant to return because I've read it 3 times now and it still doesn't make sense.确切地了解此查询要返回的内容可能会有所帮助,因为我现在已经阅读了 3 次,但仍然没有意义。 :) :)

You are selecting ServerEquipment where their Struct.Paremt.Parent.ObjectID = the Section ID AND their plan Equipment's contain, from what I can make out, the earliest Equipment record in that set.您正在选择 ServerEquipment,其中他们的 Struct.Paremt.Parent.ObjectID = 部分 ID 和他们的计划设备包含,据我所知,该集合中最早的设备记录。 That Contains check is what makes no sense because it is just looking for the existence of a select row within that set without any external criteria? Contains检查是没有意义的,因为它只是在没有任何外部条件的情况下寻找该集合中是否存在选择行? I mean boiled down it looks like .Where(x => x.Children.Select(c => c.ChildId).Contains(x.Children.OrderByDescending(c2 => c2.BirthDate).Select(c2 => c2.ChildId).FirstOrDefault()) which is pretty much a fancy way of wasting the database's time. Ie Where Children Contains an oldest child. (Well of course it does.) So I can only assume I've missed something there, but I'd really hate to try and pick up an entity structure and queries like that 6 months from now.. :)我的意思是归结起来它看起来像.Where(x => x.Children.Select(c => c.ChildId).Contains(x.Children.OrderByDescending(c2 => c2.BirthDate).Select(c2 => c2.ChildId).FirstOrDefault())这几乎是一种浪费数据库时间的奇特方式。即其中儿童包含一个最大的孩子。(当然是这样。)所以我只能假设我错过了那里的一些东西,但我真的很不想在 6 个月后尝试选择这样的实体结构和查询.. :)

A contains check from it's own child collection without any external criteria doesn't make sense.在没有任何外部条件的情况下,包含来自它自己的子集合的检查是没有意义的。 Normally these types of queries would look at a child collection to see if they contained some matching criteria which would be satisfied by an Any() type check within the overlying Where clause.通常,这些类型的查询会查看子集合,以查看它们是否包含某些匹配条件,这些条件将通过覆盖Where子句中的Any()类型检查来满足。 It might help to look again at exactly what you want to filter to see if this query can be simplified and avoid this breaking change.再次查看您要过滤的确切内容以查看是否可以简化此查询并避免这种破坏性更改可能会有所帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 无法翻译 LINQ 表达式。 要么以可翻译的形式重写查询,要么切换到客户评估 - The LINQ expression could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation 无法翻译 LINQ 表达式 g.Inner)'。 以可以翻译的形式重写查询 - The LINQ expression g.Inner)' could not be translated. Either rewrite the query in a form that can be translate 得到“无法翻译。 以可翻译的形式重写查询”,.NET Corel 中的异常 - Getting “could not be translated. Either rewrite the query in a form that can be translated”, exception in .NET Corel 无法在 EF Core 3.1 中翻译 LINQ 表达式 - The LINQ expression could not be translated in EF Core 3.1 要么以可翻译的形式重写查询,要么显式切换到客户端评估……通过插入对 'AsEnumerable 的调用 - Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly… by inserting a call to 'AsEnumerable EF Core (LINQ) - 无法翻译查询表达式 - EF Core (LINQ) - The Query expression could not be Translated 无法翻译 LINQ 表达式。 通过插入对“AsEnumerable”、“AsAsyncEnumerable”、“ToList”的调用来显式评估客户端 - LINQ expression could not be translated. client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList' EF Core 3.1 - 无法翻译 LINQ 表达式(左连接与 group by) - EF Core 3.1 - The LINQ expression could not be translated (left joins with group by) LINQ 无法翻译表达式(EF Core 中的深度查询) - LINQ Expression could not be translated (Deep Query in EF Core) 无法翻译 EF Core Linq 表达式 - EF Core Linq expression could not be translated
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM