Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SingleOrDefaultAsync throws NullReference Exception if source is empty #17056

Closed
BenjaminAbt opened this issue Aug 9, 2019 · 1 comment

Comments

@BenjaminAbt
Copy link

commented Aug 9, 2019

We have updated our source code from Preview 5 to Preview 7.
We found a bug in SingleOrDefaultAsync. As soon as the collection is empty, a NullReference exception is thrown.

Steps to reproduce

This is our in-memory test

[Theory, AutoMoqData]
public async Task HandleTests_Without_User(Mock<IEventDispatcher> evntDp, Mock<IActivationkeyGenerator> keyMock, string userName)
{
    // Connection
    DbContextOptions<SampleDbContext > options = new DbContextOptionsBuilder<SampleDbContext >()
              .UseInMemoryDatabase(Guid.NewGuid().ToString()).Options;

    // Execute
    using (SampleDbContext = new SampleDbContext (options))
    {
        // Notification
        UserAddedEventNotification notification = new UserAddedEventNotification(1, userName);

        // Command Handler
        SampleHandler ch = new SampleHandler (evntDp.Object, dbContext, keyMock.Object);

        // Execute
        Func<Task> f = async () => await ch.Handle(notification, default);

         await f.Should().ThrowAsync<UserNotFoundException>();
    }
}

The actually interesting snippet is the following:

var userEntity = await _dbContext.Users.Where(x => x.Id == userId).SingleOrDefaultAsync(cancellationToken);
if (userEntity is null)
{
    throw new UserNotFoundException();
}

SingleOrDefaultAsync throws a NullReference Exception, if no entry was found.
Works if entry was found.

"Object reference not set to an instance of an object." at Microsoft.EntityFrameworkCore.InMemory.Query.Pipeline.InMemoryShapedQueryCompilingExpressionVisitor.AsyncQueryingEnumerable1.AsyncEnumerator.MoveNextAsync() at Microsoft.EntityFrameworkCore.Query.Pipeline.ShapedQueryCompilingExpressionVisitor.d__17'1.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Microsoft.EntityFrameworkCore.Query.Pipeline.ShapedQueryCompilingExpressionVisitor.d__17'1.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()

However, the following workaround works:

var userEntities = await _dbContext.Users.Where(x => x.Id == userId).ToListAsync(cancellationToken);
var userEntity = userEntities.SingleOrDefault();
if (userEntity is null)
{
    throw new UserNotFoundException();
}

Further technical details

EF Core version: 3.0.0-preview7.19362.6
Database Provider: Microsoft.EntityFrameworkCore.InMemory
Operating system: 10.0.17763.615
IDE: 16.3.0 Preview 1.0

@ajcvickers

This comment has been minimized.

Copy link
Member

commented Aug 9, 2019

Duplicate of #16099

@ajcvickers ajcvickers marked this as a duplicate of #16099 Aug 9, 2019

@ajcvickers ajcvickers closed this Aug 9, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.