简体   繁体   English

C# EF Core 5.0 GroupBy Select 条件计数无法翻译

[英]C# EF Core 5.0 GroupBy Select Conditional Count could not be translated

I have an Individual Species observation and an Observation group where there is a many-to-many relationship (IndividualObservationGroup).我有一个个体物种观察和一个观察组,其中存在多对多关系(IndividualObservationGroup)。 I am now getting an error in the following code since I moved from efcore2.1 to efcore5.0.自从我从 efcore2.1 迁移到 efcore5.0 后,我现在在以下代码中遇到错误。 I am now receiving an error:我现在收到一个错误:

System.InvalidOperationException: The LINQ expression 'GroupByShaperExpression: KeySelector: i.ObservationGroupGuid, ElementSelector:EntityShaperExpression: EntityType: IndividualObservationGroup ValueBufferExpression: ProjectionBindingExpression: EmptyProjectionMember IsNullable: False System.InvalidOperationException:LINQ 表达式'GroupByShaperExpression:KeySelector:i.ObservationGroupGuid,ElementSelector:EntityShaperExpression:EntityType:IndividualObservationGroup ValueBufferExpression:ProjectionBindingExpression:EmptyProjectionMember IsNullable:False

    .Count(x => x.IndividualObservation.SexCodeId == (Nullable<int>)1)' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.

Here is the code:这是代码:

var queryable = context.IndividualObservationGroup.AsNoTracking()
                       .Include(obg => obg.ObservationGroup)
                       .Include(obg => obg.IndividualObservation)
                           .ThenInclude(io => io.SetDetail)
                       .Where(items => String.Equals(items.ObservationGroupGuid, lookupItem.ObservationGroupGuid) &&
                                                     items.GroupNumber == lookupItem.GroupNumber &&
                                                     items.TargetItem == lookupItem.TargetItem)
                                            .GroupBy(items => items.ObservationGroupGuid)
                                            .Select(items => new
                                            {
                                                TallyKey = items.Key,
                                                Females = items.Count(x => x.IndividualObservation.SexCodeId == 1),
                                                Males = items.Count(x => x.IndividualObservation.SexCodeId == 2),
                                                UnSexed = items.Count(x => x.IndividualObservation.SexCodeId == 3),
                                                numberFromCurrentSet = items.Count(x => x.IndividualObservation.ParentGuid == setDetailGuid)
                                            });
var group = await queryable.FirstOrDefaultAsync();

After getting come feedback from the efcore github site ( https://github.com/dotnet/efcore/issues/24238 ) The recommendation was to introduce the join between the tables, even though I had it specified in the model builder db context code: After getting come feedback from the efcore github site ( https://github.com/dotnet/efcore/issues/24238 ) The recommendation was to introduce the join between the tables, even though I had it specified in the model builder db context code :

modelBuilder.Entity<IndividualObservation>(entity =>
            {
                entity.HasKey(x => x.GUID);
                entity.HasMany(x => x.ObservationGroups)
                       .WithOne(e => e.IndividualObservation)
                       .HasForeignKey(e => e.IndividualObservationGuid);
            });
modelBuilder.Entity<ObservationGroup>(entity =>
            {
                entity.HasKey(x => x.GUID);
                entity.HasIndex(x => x.GUID);
                entity.HasMany(x => x.IndividualObservations)
                       .WithOne(e => e.ObservationGroup)
                       .HasForeignKey(e => e.ObservationGroupGuid);
            });
modelBuilder.Entity<IndividualObservationGroup>(entity =>
            {
                entity.HasKey(io => new { io.IndividualObservationGuid, io.ObservationGroupGuid });
            });

The reason given was: "Currently EF Core doesn't expand navigations after a GroupBy operator is applied. You using IndividualObservation navigation hence it fails. As a work-around you can expand navigation manually using join before applying GroupBy and it should work."给出的原因是:“当前,EF Core 在应用 GroupBy 运算符后不会扩展导航。您使用的是 IndividualObservation 导航,因此它会失败。作为一种解决方法,您可以在应用 GroupBy 之前使用 join 手动扩展导航,它应该可以工作。”

So I added the following joins and it works:所以我添加了以下连接并且它有效:

var queryable = context.IndividualObservationGroup.AsNoTracking()
                       .Include(obg => obg.ObservationGroup)
                       .Include(obg => obg.IndividualObservation)
                           .ThenInclude(io => io.SetDetail)
                       .Join(context.ObservationGroup,
                                 iog => iog.ObservationGroupGuid,
                                 og => og.GUID,
                                 (iog, og) => new {
                                     IndividualObservationGuid = iog.IndividualObservationGuid,
                                     GroupNumber = iog.GroupNumber,
                                     TargetItem = iog.TargetItem,
                                     ObservationGroupGuid = og.GUID
                            })
                        .Join(context.IndividualObservation,
                                     iog => iog.IndividualObservationGuid,
                                     io => io.GUID,
                                     (iog, io) => new {
                                           ObservationGroupGuid = iog.ObservationGroupGuid,
                                           GroupNumber = iog.GroupNumber,
                                           TargetItem = iog.TargetItem,
                                           IndividualObservationGuid = io.GUID,
                                           SetDetailGuid = io.ParentGuid,
                                           SexCodeId = io.SexCodeId
                              })
                       .Where(items => String.Equals(items.ObservationGroupGuid, lookupItem.ObservationGroupGuid) &&
                                                     items.GroupNumber == lookupItem.GroupNumber &&
                                                     items.TargetItem == lookupItem.TargetItem)
                       .GroupBy(items => items.ObservationGroupGuid)
                       .Select(items => new
                                     {
                                        TallyKey = items.Key,
                                        Females = items.Count(x => x.SexCodeId == 1),
                                        Males = items.Count(x => x.SexCodeId == 2),
                                        UnSexed = items.Count(x => x.SexCodeId == 3),
                                        numberFromCurrentSet = items.Count(x => x.SetDetailGuid == setDetailGuid)
                                       });
var group = await queryable.FirstOrDefaultAsync();

So Adding the two join statements allowed me to avoid the IEnumerable requirement and running the query on the client.因此,添加两个连接语句使我能够避免 IEnumerable 要求并在客户端上运行查询。 Just hope that sometime in the future efcore can take more advantage of the joins setup in the modelbuilder statement and use it for IQueryable beyond just navigation.只是希望将来某个时候 efcore 可以更多地利用 modelbuilder 语句中的连接设置,并将其用于 IQueryable 而不仅仅是导航。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM