Skip to content

Commit

Permalink
Query: Support ToQuerySql (#21831)
Browse files Browse the repository at this point in the history
Resolves #17063
  • Loading branch information
smitpatel authored Jul 29, 2020
1 parent 8cc9a3f commit e57ec85
Show file tree
Hide file tree
Showing 19 changed files with 151 additions and 151 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,11 @@ protected override Expression VisitExtension(Expression extensionExpression)

return CreateShapedQueryExpression(entityType, queryExpression);

case QueryRootExpression queryRootExpression
when queryRootExpression.EntityType.GetSqlQueryMappings().FirstOrDefault(m => m.IsDefaultSqlQueryMapping)?.SqlQuery is ISqlQuery querySql:
return Visit(new FromSqlQueryRootExpression(
queryRootExpression.EntityType, querySql.Sql, Expression.Constant(Array.Empty<object>(), typeof(object[]))));

default:
return base.VisitExtension(extensionExpression);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,12 @@ FROM root c
WHERE ((c[""Discriminator""] = ""Customer"") AND (c[""City""] = ""London""))");
}

[ConditionalTheory(Skip = "Issue #17246")]
public override Task KeylessEntity_with_included_nav(bool async)
{
return base.KeylessEntity_with_included_nav(async);
}

public override async Task KeylessEntity_with_defining_query(bool async)
{
await base.KeylessEntity_with_defining_query(async);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con
modelBuilder
.Entity<CustomerQueryWithQueryFilter>()
.HasDiscriminator<string>("Discriminator").HasValue("Customer");

#pragma warning disable CS0618 // Type or member is obsolete
modelBuilder
.Entity<CustomerQuery>().Metadata.SetDefiningQuery(null);
modelBuilder
.Entity<OrderQuery>().Metadata.SetDefiningQuery(null);
modelBuilder
.Entity<ProductQuery>().Metadata.SetDefiningQuery(null);
modelBuilder
.Entity<CustomerQueryWithQueryFilter>().Metadata.SetDefiningQuery(null);
#pragma warning restore CS0618 // Type or member is obsolete
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using Microsoft.EntityFrameworkCore.TestModels.Northwind;
using Microsoft.EntityFrameworkCore.TestUtilities;
using Xunit.Abstractions;

Expand All @@ -13,5 +14,10 @@ public NorthwindChangeTrackingQueryInMemoryTest(NorthwindQueryInMemoryFixture<No
{
//TestLoggerFactory.TestOutputHelper = testOutputHelper;
}

protected override NorthwindContext CreateNoTrackingContext()
=> new NorthwindInMemoryContext(
new DbContextOptionsBuilder(Fixture.CreateOptions())
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking).Options);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Linq;
using Microsoft.EntityFrameworkCore.TestModels.Northwind;

namespace Microsoft.EntityFrameworkCore.Query
{
public class NorthwindInMemoryContext : NorthwindContext
{
public NorthwindInMemoryContext(DbContextOptions options)
: base(options)
{
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);

InMemoryEntityTypeBuilderExtensions.ToQuery(
modelBuilder.Entity<CustomerQuery>(),
() => Customers.Select(
c => new CustomerQuery
{
Address = c.Address,
City = c.City,
CompanyName = c.CompanyName,
ContactName = c.ContactName,
ContactTitle = c.ContactTitle
}));

InMemoryEntityTypeBuilderExtensions.ToQuery(
modelBuilder.Entity<OrderQuery>(),
() => Orders.Select(o => new OrderQuery { CustomerID = o.CustomerID }));

InMemoryEntityTypeBuilderExtensions.ToQuery(
modelBuilder.Entity<ProductQuery>(),
() => Products.Where(p => !p.Discontinued)
.Select(
p => new ProductQuery
{
ProductID = p.ProductID,
ProductName = p.ProductName,
CategoryName = "Food"
}));

InMemoryEntityTypeBuilderExtensions.ToQuery(
modelBuilder.Entity<CustomerQueryWithQueryFilter>(),
() => Customers.Select(
c => new CustomerQueryWithQueryFilter
{
CompanyName = c.CompanyName,
OrderCount = c.Orders.Count(),
SearchTerm = SearchTerm
}));
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

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

namespace Microsoft.EntityFrameworkCore.Query
Expand All @@ -26,5 +29,11 @@ public override void KeylessEntity_by_database_view()
public override void Entity_mapped_to_view_on_right_side_of_join()
{
}

public override async Task KeylessEntity_with_included_nav(bool async)
{
await Assert.ThrowsAsync<InvalidOperationException>(() => base.KeylessEntity_with_included_nav(async));
}

}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.TestUtilities;

Expand All @@ -10,5 +11,7 @@ public class NorthwindQueryInMemoryFixture<TModelCustomizer> : NorthwindQueryFix
where TModelCustomizer : IModelCustomizer, new()
{
protected override ITestStoreFactory TestStoreFactory => InMemoryTestStoreFactory.Instance;

protected override Type ContextType => typeof(NorthwindInMemoryContext);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -709,9 +709,8 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
#pragma warning disable CS0618 // Type or member is obsolete
modelBuilder.Entity<CustomerView19708>().HasNoKey().ToQuery(Build_Customers_Sql_View_InMemory());
#pragma warning restore CS0618 // Type or member is obsolete
InMemoryEntityTypeBuilderExtensions.ToQuery(
modelBuilder.Entity<CustomerView19708>().HasNoKey(), Build_Customers_Sql_View_InMemory());
}

private Expression<Func<IQueryable<CustomerView19708>>> Build_Customers_Sql_View_InMemory()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con
modelBuilder.Entity<Lilt>().Property(e => e.SugarGrams).HasColumnName("SugarGrams");
modelBuilder.Entity<Tea>().Property(e => e.CaffeineGrams).HasColumnName("CaffeineGrams");

#pragma warning disable CS0618 // Type or member is obsolete
modelBuilder.Entity<AnimalQuery>().HasNoKey().ToQuery(
() => context.Set<AnimalQuery>().FromSqlRaw("SELECT * FROM Animals"));
#pragma warning restore CS0618 // Type or member is obsolete
modelBuilder.Entity<AnimalQuery>().HasNoKey().ToQuerySql("SELECT * FROM Animals");
modelBuilder.Entity<KiwiQuery>().HasDiscriminator().HasValue("Kiwi");
modelBuilder.Entity<EagleQuery>().HasDiscriminator().HasValue("Eagle");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ public NorthwindRelationalContext(DbContextOptions options)
{
}

public string _empty = string.Empty;

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
Expand All @@ -27,23 +26,10 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
modelBuilder.Entity<CustomerOrderHistory>().HasKey(coh => coh.ProductName);
modelBuilder.Entity<MostExpensiveProduct>().HasKey(mep => mep.TenMostExpensiveProducts);

#pragma warning disable CS0618 // Type or member is obsolete
modelBuilder.Entity<CustomerQuery>().HasNoKey().ToQuery(
() => CustomerQueries.FromSqlInterpolated(
$"SELECT [c].[CustomerID] + {_empty} as [CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] FROM [Customers] AS [c]"
));

modelBuilder
.Entity<OrderQuery>()
.HasNoKey()
.ToQuery(
() => Orders
.FromSqlRaw(@"select * from ""Orders""")
.Select(
o => new OrderQuery { CustomerID = o.CustomerID }));
#pragma warning restore CS0618 // Type or member is obsolete

modelBuilder.Entity<ProductView>().HasNoKey().ToView("Alphabetical list of products");
modelBuilder.Entity<CustomerQuery>().ToQuerySql("SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] FROM [Customers] AS [c]");

modelBuilder.Entity<OrderQuery>().ToQuerySql(@"select * from ""Orders""");
modelBuilder.Entity<ProductView>().ToView("Alphabetical list of products");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public void Model_differ_does_not_detect_views_with_weak_types()
}

[ConditionalFact]
public void Model_differ_does_not_detect_queries()
public void Model_differ_does_not_detect_defining_queries()
{
DbContext context = null;
Execute(
Expand All @@ -72,6 +72,15 @@ public void Model_differ_does_not_detect_queries()
result => Assert.Empty(result));
}

[ConditionalFact]
public void Model_differ_does_not_detect_queries()
{
Execute(
_ => { },
modelBuilder => modelBuilder.Entity<TestKeylessType>().HasNoKey().ToQuerySql("SELECT * FROM Vista"),
result => Assert.Empty(result));
}

[ConditionalFact]
public void Model_differ_detects_adding_store_type()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ var results
.Where(cq => cq.OrderCount > 0)
.ToArray();

Assert.Equal(4, results.Length);
Assert.Equal(89, results.Length);
}

[ConditionalTheory]
Expand All @@ -82,7 +82,7 @@ public virtual Task KeylessEntity_with_defining_query(bool async)
ss => ss.Set<OrderQuery>().Where(ov => ov.CustomerID == "ALFKI"));
}

[ConditionalTheory]
[ConditionalTheory(Skip = "Issue#21828")]
[MemberData(nameof(IsAsyncData))]
public virtual Task KeylessEntity_with_defining_query_and_correlated_collection(bool async)
{
Expand Down Expand Up @@ -111,46 +111,30 @@ from o in ss.Set<OrderQuery>().Where(ov => ov.CustomerID == c.CustomerID)

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual async Task KeylessEntity_with_included_nav(bool async)
{
using var ctx = CreateContext();
if (async)
{
await Assert.ThrowsAsync<InvalidOperationException>(
() => (from ov in ctx.Set<OrderQuery>().Include(ov => ov.Customer)
where ov.CustomerID == "ALFKI"
select ov).ToListAsync());
}
else
{
await Assert.ThrowsAsync<InvalidOperationException>(
() => Task.FromResult(
(from ov in ctx.Set<OrderQuery>().Include(ov => ov.Customer)
where ov.CustomerID == "ALFKI"
select ov).ToList()));
}
public virtual Task KeylessEntity_with_included_nav(bool async)
{
return AssertQuery(
async,
ss => from ov in ss.Set<OrderQuery>().Include(ov => ov.Customer)
where ov.CustomerID == "ALFKI"
select ov,
elementAsserter: (e, a) => AssertInclude(e, a, new ExpectedInclude<OrderQuery>(ov => ov.Customer)),
entryCount: 1);
}

[ConditionalTheory]
[ConditionalTheory(Skip = "Issue#21828")]
[MemberData(nameof(IsAsyncData))]
public virtual async Task KeylessEntity_with_included_navs_multi_level(bool async)
{
using var ctx = CreateContext();
if (async)
{
await Assert.ThrowsAsync<InvalidOperationException>(
() => (from ov in ctx.Set<OrderQuery>().Include(ov => ov.Customer.Orders)
where ov.CustomerID == "ALFKI"
select ov).ToListAsync());
}
else
{
await Assert.ThrowsAsync<InvalidOperationException>(
() => Task.FromResult(
(from ov in ctx.Set<OrderQuery>().Include(ov => ov.Customer.Orders)
where ov.CustomerID == "ALFKI"
select ov).ToList()));
}
public virtual Task KeylessEntity_with_included_navs_multi_level(bool async)
{
return AssertQuery(
async,
ss => from ov in ss.Set<OrderQuery>().Include(ov => ov.Customer.Orders)
where ov.CustomerID == "ALFKI"
select ov,
elementAsserter: (e, a) => AssertInclude(e, a,
new ExpectedInclude<OrderQuery>(ov => ov.Customer),
new ExpectedInclude<Customer>(c => c.Orders, "Customer")),
entryCount: 1);
}

[ConditionalTheory]
Expand Down
Loading

0 comments on commit e57ec85

Please sign in to comment.