简体   繁体   中英

EF 7/Core: Getting count of records in child table

I tried asking posing this question/problem in the issues section of the EF Core GitHub but didn't get any response, so I have to assume I was asking in the wrong place...

I'm working with the EntityFramework.Core and EntityFramework.MicrosoftSqlServer 7.0.0-rc1-final packages, and I'm trying to do something through code that looks like the following SQL:

SELECT COUNT(*)
FROM [UploadPackage] [up]
INNER JOIN [RawClip] [rc] on [up].[Id] = [rc].[PackageId]
WHERE [up].[UserId] IN (1,2,3)

I've tried the following:

Option 1:

DbContext.UploadPackages.Include(up => up.Clips).Where(up => userIds.Contains(up.UserId)).SelectMany(u => u.Clips).CountAsync()

Option 2:

DbContext.RawClips.Include(rc => rc.Package).Where(rc => userIds.Contains(rc.Package.UserId)).CountAsync()

The relationships are configured using the Fluent API like so:

modelBuilder.Entity<UploadPackage>().HasMany(up => up.Clips).WithOne(rc => rc.Package);
modelBuilder.Entity<RawClip>().HasOne(rc => rc.Package).WithMany(up => up.Clips);

Option 1 generates the following SQL:

SELECT [up].[Id], [up].[AssetId], [up].[FileName], [up].[FileSize], [up].[PackageId], [up].[Path], [up].[ProxyUrl], [up].[StatusDetails], [up].[StatusId], [up].[ThumbnailUrl], [up].[UploadCompletedDateTime], [up].[UploadStartedDateTime], [r].[Id], [r].[AssetId], [r].[FileName], [r].[FileSize], [r].[PackageId], [r].[Path], [r].[ProxyUrl], [r].[StatusDetails], [r].[StatusId], [r].[ThumbnailUrl], [r].[UploadCompletedDateTime], [r].[UploadStartedDateTime], [up].[Id]
FROM [RawClip] AS [up]
CROSS JOIN [RawClip] AS [r]
WHERE [up].[UserId] IN (2, 3, 4, 1)

As you can see, it's joining the RawClip table to itself. On one side of the join, it's giving the table the alias "[up]" which seems to be a reference to UploadPackage, even though the table it's aliasing is actually the RawClip table. This ultimately throws an error because of the where clause trying to filter on the column "[up].[UserId]", which exists on the UploadPackage table, but not the RawClip table.

Option 2 fails without generating any SQL. Here's the error with stack trace:

InvalidOperationException: Sequence contains more than one element
System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
Microsoft.Data.Entity.Query.EntityQueryModelVisitor.<>c__DisplayClass79_0`1.<BindMemberExpression>b__0(IEnumerable`1 ps, IQuerySource qs)
Microsoft.Data.Entity.Query.EntityQueryModelVisitor.BindMemberExpressionCore[TResult](MemberExpression memberExpression, IQuerySource querySource, Func`3 memberBinder)
Microsoft.Data.Entity.Query.EntityQueryModelVisitor.BindMemberExpression[TResult](MemberExpression memberExpression, IQuerySource querySource, Func`3 memberBinder)
Microsoft.Data.Entity.Query.EntityQueryModelVisitor.BindMemberExpression(MemberExpression memberExpression, Action`2 memberBinder)
Microsoft.Data.Entity.Query.ExpressionVisitors.Internal.RequiresMaterializationExpressionVisitor.VisitMember(MemberExpression memberExpression)
System.Linq.Expressions.MemberExpression.Accept(ExpressionVisitor visitor)
System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
Microsoft.Data.Entity.Query.ExpressionVisitors.ExpressionVisitorBase.Visit(Expression expression)
Remotion.Linq.Clauses.ResultOperators.ContainsResultOperator.TransformExpressions(Func`2 transformation)
Remotion.Linq.QueryModel.TransformExpressions(Func`2 transformation)
Microsoft.Data.Entity.Query.ExpressionVisitors.Internal.RequiresMaterializationExpressionVisitor.VisitSubQuery(SubQueryExpression subQueryExpression)
Remotion.Linq.Clauses.Expressions.SubQueryExpression.Accept(ExpressionVisitor visitor)
System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
2000 
Microsoft.Data.Entity.Query.ExpressionVisitors.ExpressionVisitorBase.Visit(Expression expression)
Remotion.Linq.Clauses.WhereClause.TransformExpressions(Func`2 transformation)
Remotion.Linq.QueryModel.TransformExpressions(Func`2 transformation)
Microsoft.Data.Entity.Query.ExpressionVisitors.Internal.RequiresMaterializationExpressionVisitor.FindQuerySourcesRequiringMaterialization(QueryModel queryModel)
Microsoft.Data.Entity.Query.QueryCompilationContext.FindQuerySourcesRequiringMaterialization(EntityQueryModelVisitor queryModelVisitor, QueryModel queryModel)
Microsoft.Data.Entity.Query.EntityQueryModelVisitor.CreateAsyncQueryExecutor[TResult](QueryModel queryModel)
Microsoft.Data.Entity.Storage.Database.CompileAsyncQuery[TResult](QueryModel queryModel)
Microsoft.Data.Entity.Query.Internal.QueryCompiler.<>c__DisplayClass19_0`1.<CompileAsyncQuery>b__0()
Microsoft.Data.Entity.Query.Internal.CompiledQueryCache.GetOrAddAsyncQuery[TResult](Object cacheKey, Func`1 compiler)
Microsoft.Data.Entity.Query.Internal.QueryCompiler.CompileAsyncQuery[TResult](Expression query)
Microsoft.Data.Entity.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken)
Microsoft.Data.Entity.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken)
Microsoft.Data.Entity.EntityFrameworkQueryableExtensions.ExecuteAsync[TSource,TResult](MethodInfo operatorMethodInfo, IQueryable`1 source, CancellationToken cancellationToken)
Microsoft.Data.Entity.EntityFrameworkQueryableExtensions.CountAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)

Am I doing something wrong? Is there a better way to achieve what I'm trying to do? It seems like a fairly simple use case, so I imagine there has to be some way to make this work...

I eventually received a reply on my issue posted on the EF Core GitHub:

https://github.com/aspnet/EntityFramework/issues/5413

This issue was a bug in RC1 that is now fixed in RC2. I've migrated to RC2, and all looks good now.

Try this:

DbContext.UploadPackages.Where(up => userIds.Contains(up.UserId)).SelectMany(u => u.Clips).CountAsync();

You should not include if you eagerly say what navigation property you wan

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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