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

Fix exception on sequential single/first call to different types #91

Merged
merged 1 commit into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
Expand All @@ -40,7 +39,6 @@ public class MongoClientWrapper : IMongoClientWrapper
private readonly IDiagnosticsLogger<DbLoggerCategory.Database.Command> _commandLogger;
private readonly IMongoClient _client;
private readonly IMongoDatabase _database;
private PropertyInfo? _getLoggedStages;
private string DatabaseName => _database.DatabaseNamespace.DatabaseName;

/// <summary>
Expand Down Expand Up @@ -88,8 +86,8 @@ private IEnumerable<T> ExecuteScalar<T>(MongoExecutableQuery executableQuery)
var result = executableQuery.Provider.Execute<T>(executableQuery.Query);

// We need to get this via reflection from the Mongo C# Driver for now.
_getLoggedStages ??= executableQuery.Provider.GetType().GetProperty("LoggedStages");
if (_getLoggedStages?.GetValue(executableQuery.Provider) is BsonDocument[] loggedStages)
var getLoggedStages = executableQuery.Provider.GetType().GetProperty("LoggedStages");
if (getLoggedStages?.GetValue(executableQuery.Provider) is BsonDocument[] loggedStages)
{
_commandLogger.ExecutedMqlQuery(executableQuery.CollectionNamespace, loggedStages);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,9 @@
namespace MongoDB.EntityFrameworkCore.FunctionalTests.Query;

[XUnitCollection(nameof(SampleGuidesFixture))]
public class FirstSingleTests : IDisposable, IAsyncDisposable
public class FirstSingleTests(SampleGuidesFixture fixture) : IDisposable, IAsyncDisposable
{
private readonly GuidesDbContext _db;

public FirstSingleTests(SampleGuidesFixture fixture)
{
_db = GuidesDbContext.Create(fixture.MongoDatabase);
}
private readonly GuidesDbContext _db = GuidesDbContext.Create(fixture.MongoDatabase);

[Fact]
public void First()
Expand All @@ -42,27 +37,118 @@ public async Task FirstAsync()
Assert.Equal("Earth", result.name);
}

[Fact]
public void FirstOrDefault()
{
var result = _db.Planets.OrderBy(p => p.name).FirstOrDefault();
Assert.NotNull(result);
Assert.Equal("Earth", result.name);
}

[Fact]
public async Task FirstOrDefaultAsync()
{
var result = await _db.Planets.OrderBy(p => p.name).FirstOrDefaultAsync();
Assert.NotNull(result);
Assert.Equal("Earth", result.name);
}

[Fact]
public void FirstOrDefault_with_two_different_types_sequentially()
{
var planet = _db.Planets.FirstOrDefault();
Assert.NotNull(planet);

var moon = _db.Moons.FirstOrDefault();
Assert.NotNull(moon);
}

[Fact]
public void First_with_no_result()
{
var ex = Assert.Throws<InvalidOperationException>(() => _db.Planets.Skip(100).First());
Assert.Equal("Sequence contains no elements", ex.Message);
}

[Fact]
public async Task FirstAsync_with_no_result()
{
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => _db.Planets.Skip(100).FirstAsync());
Assert.Equal("Sequence contains no elements", ex.Message);
}

[Fact]
public void FirstOrDefault_with_no_result()
{
var result = _db.Planets.Skip(100).FirstOrDefault();
Assert.Null(result);
}

[Fact]
public async Task FirstOrDefaultAsync_with_no_result()
{
var result = await _db.Planets.Skip(100).FirstOrDefaultAsync();
Assert.Null(result);
}

[Fact]
public void First_predicate()
{
var result = _db.Planets.First(p => p.orderFromSun == 1);
Assert.Equal("Mercury", result.name);
}

[Fact]
public async Task FirstAsync_predicate()
{
var result = await _db.Planets.FirstAsync(p => p.orderFromSun == 1);
Assert.Equal("Mercury", result.name);
}

[Fact]
public void FirstOrDefault_predicate()
{
var result = _db.Planets.FirstOrDefault(p => p.orderFromSun == 1);
Assert.NotNull(result);
Assert.Equal("Mercury", result.name);
}

[Fact]
public async Task FirstOrDefaultAsync_predicate()
{
var result = await _db.Planets.FirstOrDefaultAsync(p => p.orderFromSun == 1);
Assert.NotNull(result);
Assert.Equal("Mercury", result.name);
}

[Fact]
public void First_predicate_no_results()
{
var ex = Assert.Throws<InvalidOperationException>(() => _db.Planets.First(p => p.orderFromSun == 10));
Assert.Equal("Sequence contains no elements", ex.Message);
}

[Fact]
public async Task FirstAsync_predicate_no_results()
{
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => _db.Planets.FirstAsync(p => p.orderFromSun == 10));
Assert.Equal("Sequence contains no elements", ex.Message);
}

[Fact]
public void FirstOrDefault_predicate_no_results()
{
var result = _db.Planets.FirstOrDefault(p => p.orderFromSun == 10);
Assert.Null(result);
}

[Fact]
public async Task FirstOrDefaultAsync_predicate_no_results()
{
var result = await _db.Planets.FirstOrDefaultAsync(p => p.orderFromSun == 10);
Assert.Null(result);
}

[Fact]
public void Single()
{
Expand All @@ -77,41 +163,164 @@ public async Task SingleAsync()
Assert.Equal("Earth", result.name);
}

[Fact]
public void SingleOrDefault()
{
var result = _db.Planets.Where(p => p.name == "Earth").SingleOrDefault();
Assert.NotNull(result);
Assert.Equal("Earth", result.name);
}

[Fact]
public async Task SingleOrDefaultAsync()
{
var result = await _db.Planets.Where(p => p.name == "Earth").SingleOrDefaultAsync();
Assert.NotNull(result);
Assert.Equal("Earth", result.name);
}

[Fact]
public void Single_with_no_results()
{
var ex = Assert.Throws<InvalidOperationException>(() => _db.Planets.Skip(100).Single());
Assert.Equal("Sequence contains no elements", ex.Message);
}

[Fact]
public async Task SingleAsync_with_no_results()
{
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => _db.Planets.Skip(100).SingleAsync());
Assert.Equal("Sequence contains no elements", ex.Message);
}

[Fact]
public void SingleOrDefault_with_no_results()
{
var result = _db.Planets.Skip(100).SingleOrDefault();
Assert.Null(result);
}

[Fact]
public async Task SingleOrDefaultAsync_with_no_results()
{
var results = await _db.Planets.Skip(100).SingleOrDefaultAsync();
Assert.Null(results);
}

[Fact]
public void Single_with_more_than_one_result()
{
var ex = Assert.Throws<InvalidOperationException>(() => _db.Planets.Skip(4).Single());
Assert.Equal("Sequence contains more than one element", ex.Message);
}

[Fact]
public async Task SingleAsync_with_more_than_one_result()
{
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => _db.Planets.Skip(4).SingleAsync());
Assert.Equal("Sequence contains more than one element", ex.Message);
}

[Fact]
public void SingleOrDefault_with_more_than_one_result()
{
var ex = Assert.Throws<InvalidOperationException>(() => _db.Planets.Skip(4).SingleOrDefault());
Assert.Equal("Sequence contains more than one element", ex.Message);
}

[Fact]
public async Task SingleOrDefaultAsync_with_more_than_one_result()
{
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => _db.Planets.Skip(4).SingleOrDefaultAsync());
Assert.Equal("Sequence contains more than one element", ex.Message);
}

[Fact]
public void Single_predicate()
{
var result = _db.Planets.Single(p => p.orderFromSun == 1);
Assert.Equal("Mercury", result.name);
}

[Fact]
public async Task SingleAsync_predicate()
{
var result = await _db.Planets.SingleAsync(p => p.orderFromSun == 1);
Assert.Equal("Mercury", result.name);
}

[Fact]
public void SingleOrDefault_predicate()
{
var result = _db.Planets.SingleOrDefault(p => p.orderFromSun == 1);
Assert.NotNull(result);
Assert.Equal("Mercury", result.name);
}

[Fact]
public async Task SingleOrDefaultAsync_predicate()
{
var result = await _db.Planets.SingleOrDefaultAsync(p => p.orderFromSun == 1);
Assert.NotNull(result);
Assert.Equal("Mercury", result.name);
}

[Fact]
public void Single_predicate_no_results()
{
var ex = Assert.Throws<InvalidOperationException>(() => _db.Planets.Single(p => p.orderFromSun == 10));
Assert.Equal("Sequence contains no elements", ex.Message);
}

[Fact]
public async Task SingleAsync_predicate_no_results()
{
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => _db.Planets.SingleAsync(p => p.orderFromSun == 10));
Assert.Equal("Sequence contains no elements", ex.Message);
}

[Fact]
public void SingleOrDefault_predicate_no_results()
{
var result = _db.Planets.SingleOrDefault(p => p.orderFromSun == 10);
Assert.Null(result);
}

[Fact]
public async Task SingleOrDefaultAsync_predicate_no_results()
{
var result = await _db.Planets.SingleOrDefaultAsync(p => p.orderFromSun == 10);
Assert.Null(result);
}

[Fact]
public void Single_predicate_with_more_than_one_result()
{
var ex = Assert.Throws<InvalidOperationException>(() => _db.Planets.Single(p => p.orderFromSun > 5));
Assert.Equal("Sequence contains more than one element", ex.Message);
}


[Fact]
public async Task SingleAsync_predicate_with_more_than_one_result()
{
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => _db.Planets.SingleAsync(p => p.orderFromSun > 5));
Assert.Equal("Sequence contains more than one element", ex.Message);
}

[Fact]
public void SingleOrDefault_predicate_with_more_than_one_result()
{
var ex = Assert.Throws<InvalidOperationException>(() => _db.Planets.SingleOrDefault(p => p.orderFromSun > 5));
Assert.Equal("Sequence contains more than one element", ex.Message);
}

[Fact]
public async Task SingleOrDefaultAsync_predicate_with_more_than_one_result()
{
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => _db.Planets.SingleOrDefaultAsync(p => p.orderFromSun > 5));
Assert.Equal("Sequence contains more than one element", ex.Message);
}

public void Dispose()
=> _db.Dispose();

Expand Down