Skip to content

Commit

Permalink
Query: Add regression test for #24368 (#25715)
Browse files Browse the repository at this point in the history
Resolves #24368
  • Loading branch information
smitpatel authored Aug 25, 2021
1 parent e2ea225 commit 717ee2c
Show file tree
Hide file tree
Showing 5 changed files with 204 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.EntityFrameworkCore.TestUtilities;

namespace Microsoft.EntityFrameworkCore.Query
{
public class SimpleQueryInMemoryTest : SimpleQueryTestBase
{
protected override ITestStoreFactory TestStoreFactory => InMemoryTestStoreFactory.Instance;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.EntityFrameworkCore.TestUtilities;

namespace Microsoft.EntityFrameworkCore.Query
{
public abstract class SimpleQueryRelationalTestBase : SimpleQueryTestBase
{
protected TestSqlLoggerFactory TestSqlLoggerFactory
=> (TestSqlLoggerFactory)ListLoggerFactory;

protected void ClearLog() => TestSqlLoggerFactory.Clear();

protected void AssertSql(params string[] expected) => TestSqlLoggerFactory.AssertBaseline(expected);
}
}
127 changes: 127 additions & 0 deletions test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Xunit;

namespace Microsoft.EntityFrameworkCore
{
public abstract class SimpleQueryTestBase : NonSharedModelTestBase
{
public static IEnumerable<object[]> IsAsyncData = new[] { new object[] { false }, new object[] { true } };

protected override string StoreName => "SimpleQueryTests";

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual async Task Multiple_nested_reference_navigations(bool async)
{
var contextFactory = await InitializeAsync<Context24368>();

using (var context = contextFactory.CreateContext())
{
var id = 1;
var staff = await context.Staff.FindAsync(3);

Assert.Equal(1, staff.ManagerId);

var query = context.Appraisals
.Include(ap => ap.Staff).ThenInclude(s => s.Manager)
.Include(ap => ap.Staff).ThenInclude(s => s.SecondaryManager)
.Where(ap => ap.Id == id);

var appraisal = async
? await query.SingleOrDefaultAsync()
: query.SingleOrDefault();

Assert.Equal(1, staff.ManagerId);

Assert.NotNull(appraisal);
Assert.Same(staff, appraisal.Staff);
Assert.NotNull(appraisal.Staff.Manager);
Assert.Equal(1, appraisal.Staff.ManagerId);
Assert.NotNull(appraisal.Staff.SecondaryManager);
Assert.Equal(2, appraisal.Staff.SecondaryManagerId);
}
}

protected class Context24368 : DbContext
{
public Context24368(DbContextOptions options)
: base(options)
{
}

public DbSet<Appraisal> Appraisals { get; set; }
public DbSet<Staff> Staff { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Staff>().HasIndex(e => e.ManagerId).IsUnique(false);
modelBuilder.Entity<Staff>()
.HasOne(a => a.Manager)
.WithOne()
.HasForeignKey<Staff>(s => s.ManagerId)
.IsRequired(false)
.OnDelete(DeleteBehavior.NoAction);

modelBuilder.Entity<Staff>().HasIndex(e => e.SecondaryManagerId).IsUnique(false);
modelBuilder.Entity<Staff>()
.HasOne(a => a.SecondaryManager)
.WithOne()
.HasForeignKey<Staff>(s => s.SecondaryManagerId)
.IsRequired(false)
.OnDelete(DeleteBehavior.NoAction);

modelBuilder.Entity<Staff>().HasData(
new Staff { Id = 1, Email = "mgr1@company.com", Logon = "mgr1", Name = "Manager 1" },
new Staff { Id = 2, Email = "mgr2@company.com", Logon = "mgr2", Name = "Manager 2", ManagerId = 1 },
new Staff { Id = 3, Email = "emp@company.com", Logon = "emp", Name = "Employee", ManagerId = 1, SecondaryManagerId = 2 }
);

modelBuilder.Entity<Appraisal>().HasData(new Appraisal()
{
Id = 1,
PeriodStart = new DateTimeOffset(new DateTime(2020, 1, 1).ToUniversalTime()),
PeriodEnd = new DateTimeOffset(new DateTime(2020, 12, 31).ToUniversalTime()),
StaffId = 3
});
}
}

protected class Appraisal
{
public int Id { get; set; }

public int StaffId { get; set; }
public Staff Staff { get; set; }

public DateTimeOffset PeriodStart { get; set; }
public DateTimeOffset PeriodEnd { get; set; }

public bool Complete { get; set; }
public bool Deleted { get; set; }
}

protected class Staff
{
public int Id { get; set; }
[MaxLength(100)]
public string Logon { get; set; }
[MaxLength(150)]
public string Email { get; set; }
[MaxLength(100)]
public string Name { get; set; }

public int? ManagerId { get; set; }
public Staff Manager { get; set; }

public int? SecondaryManagerId { get; set; }
public Staff SecondaryManager { get; set; }
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore.TestUtilities;

// ReSharper disable InconsistentNaming
namespace Microsoft.EntityFrameworkCore.Query
{
public class SimpleQuerySqlServerTest : SimpleQueryRelationalTestBase
{
protected override ITestStoreFactory TestStoreFactory => SqlServerTestStoreFactory.Instance;

public override async Task Multiple_nested_reference_navigations(bool async)
{
await base.Multiple_nested_reference_navigations(async);

AssertSql(
@"@__p_0='3'
SELECT TOP(1) [s].[Id], [s].[Email], [s].[Logon], [s].[ManagerId], [s].[Name], [s].[SecondaryManagerId]
FROM [Staff] AS [s]
WHERE [s].[Id] = @__p_0",
//
@"@__id_0='1'
SELECT TOP(2) [a].[Id], [a].[Complete], [a].[Deleted], [a].[PeriodEnd], [a].[PeriodStart], [a].[StaffId], [s].[Id], [s].[Email], [s].[Logon], [s].[ManagerId], [s].[Name], [s].[SecondaryManagerId], [s0].[Id], [s0].[Email], [s0].[Logon], [s0].[ManagerId], [s0].[Name], [s0].[SecondaryManagerId], [s1].[Id], [s1].[Email], [s1].[Logon], [s1].[ManagerId], [s1].[Name], [s1].[SecondaryManagerId]
FROM [Appraisals] AS [a]
INNER JOIN [Staff] AS [s] ON [a].[StaffId] = [s].[Id]
LEFT JOIN [Staff] AS [s0] ON [s].[ManagerId] = [s0].[Id]
LEFT JOIN [Staff] AS [s1] ON [s].[SecondaryManagerId] = [s1].[Id]
WHERE [a].[Id] = @__id_0");
}
}
}
13 changes: 13 additions & 0 deletions test/EFCore.Sqlite.FunctionalTests/Query/SimpleQuerySqliteTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.EntityFrameworkCore.TestUtilities;

namespace Microsoft.EntityFrameworkCore.Query
{
public class SimpleQuerySqliteTest : SimpleQueryRelationalTestBase
{
protected override ITestStoreFactory TestStoreFactory
=> SqliteTestStoreFactory.Instance;
}
}

0 comments on commit 717ee2c

Please sign in to comment.