Skip to content

Commit

Permalink
Fix to #13000 - Avoid creating new query roots in navigation rewrite …
Browse files Browse the repository at this point in the history
…for owned types

Fix is to add a property to NavigationRewritingExpressionVisitor. When the property is set to true owned navigations will not get converted into joins/groupjoins but rather left as they are. Because of this, we can no longer expect source of the navigation rewrite to be QSRE, but rather an arbitrary expression.
  • Loading branch information
maumar committed Aug 17, 2018
1 parent 6e96430 commit be2cab5
Show file tree
Hide file tree
Showing 3 changed files with 692 additions and 54 deletions.
257 changes: 244 additions & 13 deletions src/EFCore.Specification.Tests/Query/OwnedQueryTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,160 @@ var people
}
}

[Fact]
public virtual void Navigation_rewrite_on_owned_reference()
{
using (var ctx = CreateContext())
{
var query = ctx.Set<OwnedPerson>().Where(p => p.PersonAddress.Country.Name == "USA").Select(p => p.PersonAddress.Country.Name);
var result = query.ToList();

Assert.Equal(4, result.Count);
Assert.True(result.All(r => r == "USA"));
}
}

[Fact]
public virtual void Navigation_rewrite_on_owned_collection()
{
using (var ctx = CreateContext())
{
var query = ctx.Set<OwnedPerson>().Where(p => p.Orders.Count > 0).Select(p => p.Orders);
var result = query.ToList();

Assert.Equal(4, result.Count);
Assert.True(result.All(r => r.Count > 0));
}
}

[Fact]
public virtual void Select_many_on_owned_collection()
{
using (var ctx = CreateContext())
{
var query = ctx.Set<OwnedPerson>().SelectMany(p => p.Orders);
var result = query.ToList();

Assert.Equal(5, result.Count);
}
}

[Fact]
public virtual void Navigation_rewrite_on_owned_reference_followed_by_regular_entity()
{
using (var ctx = CreateContext())
{
var query = ctx.Set<OwnedPerson>().Select(p => p.PersonAddress.Country.Planet);
var result = query.ToList();

Assert.Equal(4, result.Count);
}
}

[Fact]
public virtual void Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_property()
{
using (var ctx = CreateContext())
{
var query = ctx.Set<OwnedPerson>().Select(p => p.PersonAddress.Country.Planet.Id);
var result = query.ToList();

Assert.Equal(4, result.Count);
Assert.True(result.All(r => r == 1));
}
}

[Fact]
public virtual void Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_collection()
{
using (var ctx = CreateContext())
{
var query = ctx.Set<OwnedPerson>().Select(p => p.PersonAddress.Country.Planet.Moons);
var result = query.ToList();

Assert.Equal(4, result.Count);
Assert.True(result.All(r => r.Count > 0));
}
}

[Fact]
public virtual void SelectMany_on_owned_reference_followed_by_regular_entity_and_collection()
{
using (var ctx = CreateContext())
{
var query = ctx.Set<OwnedPerson>().SelectMany(p => p.PersonAddress.Country.Planet.Moons);
var result = query.ToList();

Assert.Equal(4, result.Count);
Assert.True(result.All(r => r.Diameter == 3474));
}
}

[Fact]
public virtual void SelectMany_on_owned_reference_with_entity_in_between_ending_in_owned_collection()
{
using (var ctx = CreateContext())
{
var query = ctx.Set<OwnedPerson>().SelectMany(p => p.PersonAddress.Country.Planet.Star.Composition);
var result = query.ToList();

Assert.Equal(8, result.Count);
Assert.True(result.All(r => r.Name.StartsWith("H")));
}
}

[Fact]
public virtual void Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_collection_count()
{
using (var ctx = CreateContext())
{
var query = ctx.Set<OwnedPerson>().Select(p => p.PersonAddress.Country.Planet.Moons.Count);
var result = query.ToList();

Assert.Equal(4, result.Count);
Assert.True(result.All(r => r == 1));
}
}

[Fact]
public virtual void Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_another_reference()
{
using (var ctx = CreateContext())
{
var query = ctx.Set<OwnedPerson>().Select(p => p.PersonAddress.Country.Planet.Star);
var result = query.ToList();

Assert.Equal(4, result.Count);
Assert.True(result.All(r => r.Name == "Sol"));
}
}

[Fact]
public virtual void Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_another_reference_and_scalar()
{
using (var ctx = CreateContext())
{
var query = ctx.Set<OwnedPerson>().Select(p => p.PersonAddress.Country.Planet.Star.Name);
var result = query.ToList();

Assert.Equal(4, result.Count);
Assert.True(result.All(r => r == "Sol"));
}
}

[Fact]
public virtual void Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_another_reference_in_predicate_and_projection()
{
using (var ctx = CreateContext())
{
var query = ctx.Set<OwnedPerson>().Where(p => p.PersonAddress.Country.Planet.Star.Name == "Sol").Select(p => p.PersonAddress.Country.Planet.Star);
var result = query.ToList();

Assert.Equal(4, result.Count);
Assert.True(result.All(r => r.Name == "Sol"));
}
}

protected virtual DbContext CreateContext() => Fixture.CreateContext();

public abstract class OwnedQueryFixtureBase : SharedStoreFixtureBase<PoolableDbContext>
Expand Down Expand Up @@ -198,24 +352,33 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con
OwnedPersonId = 4
});
ab.OwnsOne(a => a.Country).HasData(
ab.OwnsOne(a => a.Country, cb =>
{
cb.HasData(
new
{
OwnedAddressOwnedPersonId = 1,
PlanetId = 1,
Name = "USA"
}, new
{
OwnedAddressOwnedPersonId = 2,
PlanetId = 1,
Name = "USA"
}, new
{
OwnedAddressOwnedPersonId = 3,
PlanetId = 1,
Name = "USA"
}, new
{
OwnedAddressOwnedPersonId = 4,
PlanetId = 1,
Name = "USA"
});
cb.HasOne(cc => cc.Planet).WithMany().HasForeignKey(ee => ee.PlanetId).OnDelete(DeleteBehavior.Restrict);
});
});
eb.OwnsMany(
Expand Down Expand Up @@ -272,16 +435,19 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con
BranchId = 3
});
ab.OwnsOne(a => a.Country).HasData(
new
{
OwnedAddressBranchId = 2,
Name = "Canada"
}, new
{
OwnedAddressBranchId = 3,
Name = "Canada"
});
ab.OwnsOne(a => a.Country, cb =>
{
cb.HasData(
new
{
OwnedAddressBranchId = 2,
Name = "Canada"
}, new
{
OwnedAddressBranchId = 3,
Name = "Canada"
});
});
});
});

Expand All @@ -303,12 +469,15 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con
LeafAId = 3
});
ab.OwnsOne(a => a.Country).HasData(
ab.OwnsOne(a => a.Country, cb =>
{
cb.HasData(
new
{
OwnedAddressLeafAId = 3,
Name = "Mexico"
});
});
});
});

Expand All @@ -330,14 +499,37 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con
LeafBId = 4
});
ab.OwnsOne(a => a.Country).HasData(
ab.OwnsOne(a => a.Country, cb =>
{
cb.HasData(
new
{
OwnedAddressLeafBId = 4,
Name = "Panama"
});
});
});
});

modelBuilder.Entity<Planet>(pb =>
{
pb.HasData(new Planet { Id = 1, StarId = 1 });
});

modelBuilder.Entity<Moon>(mb =>
{
mb.HasData(new Moon { Id = 1, PlanetId = 1, Diameter = 3474 });
});

modelBuilder.Entity<Star>(sb =>
{
sb.HasData(new Star { Id = 1, Name = "Sol" });
sb.OwnsMany(
s => s.Composition, ob =>
ob.HasData(
new { Id = "H", Name = "Hydrogen", StarId = 1 },
new { Id = "He", Name = "Helium", StarId = 1 }));
});
}

public override DbContextOptionsBuilder AddOptions(DbContextOptionsBuilder builder)
Expand All @@ -359,6 +551,9 @@ protected class OwnedAddress
protected class OwnedCountry
{
public string Name { get; set; }

public int? PlanetId { get; set; }
public Planet Planet { get; set; }
}

protected class OwnedPerson
Expand Down Expand Up @@ -388,5 +583,41 @@ protected class LeafB : OwnedPerson
{
public OwnedAddress LeafBAddress { get; set; }
}

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

public int StarId { get; set; }
public Star Star { get; set; }

public List<Moon> Moons { get; set; }
}

protected class Moon
{
public int Id { get; set; }
public int Diameter { get; set; }

public int PlanetId { get; set; }
}

protected class Star
{
public int Id { get; set; }
public string Name { get; set; }

public List<Element> Composition { get; set; }

public List<Planet> Planets { get; set; }
}

protected class Element
{
public string Id { get; set; }
public string Name { get; set; }

public int StarId { get; set; }
}
}
}
Loading

0 comments on commit be2cab5

Please sign in to comment.