LINQ Average conversion to SQL is correct in ver2-preview1, but incorrect in version 2
See original GitHub issueIn EF Core 2.0.0-preview1-final release the Linq Average
command was correctly converted to the SQL AVG command. In release 2.0.0 this seems to be broken.
If you are seeing an exception, include the full exceptions details (message and stack trace).
System.InvalidOperationException : Sequence contains no elements.
at Microsoft.EntityFrameworkCore.Query.QueryMethodProvider.GetResult[TResult](IEnumerable`1 valueBuffers, Boolean throwOnNullResult)
at lambda_method(Closure , QueryContext , ValueBuffer )
at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.ProjectionShaper.TypedProjectionShaper`3.Shape(QueryContext queryContext, ValueBuffer valueBuffer)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.BufferlessMoveNext(Boolean buffer)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.MoveNext()
at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext()
at System.Collections.Generic.List`1.AddEnumerable(IEnumerable`1 enumerable)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at Ver2.UnitTests.TestAverageVer2.TakeAverageOfTwoBooks() in c:\users\jonsm\Source\Repos\EfTestDifferentVersions\Ver2\UnitTests\TestAverageVer2.cs:line 73
Steps to reproduce
I have a Book
entity class with a collection of Review
entity classes that contain NumVotes
. I want to calculate the average number of votes. A Book
can have zero to many Reviews
.
My entity classes are:
public class Book
{
public int BookId { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public DateTime PublishedOn { get; set; }
public string Publisher { get; set; }
public decimal Price { get; set; }
public string ImageUrl { get; set; }
//----------------------------------------------
//relationships
public PriceOffer Promotion { get; set; }
public ICollection<Review> Reviews { get; set; }
public ICollection<BookAuthor> AuthorsLink { get; set; }
}
public class Review
{
public int ReviewId { get; set; }
public string VoterName { get; set; }
public int NumStars { get; set; }
public string Comment { get; set; }
//-----------------------------------
//Relationships
public int BookId { get; set; }
}
My test code is below, and it fails on the database query when running EF Core 2.0.0, but works correctly if running EF Core 2.0.0-preview1-final.
Note: the method TwoBooksOneWithReviews
creates two Book
entities; one with no reviews and the second with two reviews.
private class Dto
{
public string Title { get; set; }
public double? AveVotes { get; set; }
}
[Fact]
public void TakeAverageOfTwoBooks()
{
//SETUP
var options = SqliteInMemory.CreateOptions<EfCoreContext>();
using (var context = new EfCoreContext(options))
{
context.Database.EnsureCreated();
context.AddRange(SeedData.TwoBooksOneWithReviews());
context.SaveChanges();
var logs = context.SetupLogging();
//VERIFY
var result = context.Books.Select(x => new Dto
{
Title = x.Title,
AveVotes = x.Reviews.Select(y => y.NumStars).Average()
}).ToList();
//VERIFY
result.First().AveVotes.ShouldBeNull();
result.Last().AveVotes.ShouldEqual(4);
foreach (var log in logs)
{
_output.WriteLine(log);
}
}
}
If I run exactly the same test on release 2.0.0-preview1-final then it works correctly and outputs the following SQL
Executed DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT "x"."Title", (
SELECT AVG(CAST("y"."NumStars" AS REAL))
FROM "Review" AS "y"
WHERE "x"."BookId" = "y"."BookId"
) AS "AveVotes"
FROM "Books" AS "x"
Further technical details
EF Core version: 2.0.0 incorrect (2.0.0-preview1-final correct) Database Provider: Microsoft.EntityFrameworkCore.Sqlite (but fails on SqlServer too) Operating system: Windows 10 IDE: VS2017 15.3
Issue Analytics
- State:
- Created 6 years ago
- Reactions:1
- Comments:13 (9 by maintainers)
Could I ask if this bug is fixed in the planned patch update, 2.0.1? My reasons for asking this are:
DetermineAggregateThrowingBehavior
. I therefore assume its not hard to fix.Average
as an example in the book - see demo web site http://efcoreinaction.com/ (currently running EF Core 1.1.0).@anpete to follow up with a fix and we can discuss whether to patch or not.