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

.Set<> then .Any() fails after second time with .NET 6.0.100-rc.1.21458.32 / Microsoft.EntityFrameworkCore.SqlServer 6.0.0-rc.1.21452.10 #26167

Closed
recumbented opened this issue Sep 24, 2021 · 5 comments · Fixed by #27011
Assignees
Labels
area-query closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported priority-bug Issues which requires API breaks and have bigger impact hence should be fixed earlier in the release type-bug
Milestone

Comments

@recumbented
Copy link

DbContext.Set<>() .FromSql(). Any() will fail after second time with .NET 6 RC1 and EFCore SqlServer 6.0.0-rc.1.21452.10.
It will no issue with .NET 5 and EFCore 5.0.10 with no code change.

To reproduce:

public class TestDbContext : DbContext
{
    public virtual DbSet<TestTable> TestTable { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(ConnectionString);
    }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<TestTable>().HasNoKey();
    }
}

public class TestTable
{
    public String? Column1 { get; set; }
}

using (var dbContext = new TestDbContext())
{
    Console.Write("1st");
    dbContext.Set<TestTable>()
    .FromSqlRaw("SELECT N'TEXT' AS Column1")
    .Any();
    Console.WriteLine("->OK");
    
    Console.Write("2nd");
    dbContext.Set<TestTable>()
    .FromSqlRaw("SELECT N'TEXT' AS Column1")
    .Any();
    Console.WriteLine("->OK");   
}

Exception and Stack Trace

Unable to cast object of type 'Microsoft.EntityFrameworkCore.Storage.Internal.CompositeRelationalParameter' to type 'System.Object[]'.
Data = <enumerable Count: 0>
HelpLink = <null>
HResult = -2147467262
InnerException = <null>
Message = Unable to cast object of type 'Microsoft.EntityFrameworkCore.Storage.Internal.CompositeRelationalParameter' to type 'System.Object[]'.
Source = System.Private.CoreLib
StackTrace =    at System.Runtime.CompilerServices.CastHelpers.ChkCastAny(Void* toTypeHnd, Object obj)
at System.Linq.Expressions.ExpressionExtensions.GetConstantValue[T](Expression expression)
at Microsoft.EntityFrameworkCore.Query.Internal.FromSqlParameterExpandingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Query.SqlExpressions.SelectExpression.<VisitChildren>g__VisitList|120_0[T](List`1 list, Boolean inPlace, Boolean& changed, <>c__DisplayClass120_0& )
at Microsoft.EntityFrameworkCore.Query.SqlExpressions.SelectExpression.VisitChildren(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.VisitExtension(Expression node)
at System.Linq.Expressions.Expression.Accept(ExpressionVisitor visitor)
at Microsoft.EntityFrameworkCore.Query.Internal.FromSqlParameterExpandingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Query.SqlExpressions.ExistsExpression.VisitChildren(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.VisitExtension(Expression node)
at System.Linq.Expressions.Expression.Accept(ExpressionVisitor visitor)
at Microsoft.EntityFrameworkCore.Query.Internal.FromSqlParameterExpandingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Query.SqlExpressions.ProjectionExpression.VisitChildren(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.VisitExtension(Expression node)
at System.Linq.Expressions.Expression.Accept(ExpressionVisitor visitor)
at Microsoft.EntityFrameworkCore.Query.Internal.FromSqlParameterExpandingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Query.SqlExpressions.SelectExpression.<VisitChildren>g__VisitList|120_0[T](List`1 list, Boolean inPlace, Boolean& changed, <>c__DisplayClass120_0& )
at Microsoft.EntityFrameworkCore.Query.SqlExpressions.SelectExpression.VisitChildren(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.VisitExtension(Expression node)
at System.Linq.Expressions.Expression.Accept(ExpressionVisitor visitor)
at Microsoft.EntityFrameworkCore.Query.Internal.FromSqlParameterExpandingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Query.Internal.FromSqlParameterExpandingExpressionVisitor.Expand(SelectExpression selectExpression, IReadOnlyDictionary`2 parameterValues, Boolean& canCache)
at Microsoft.EntityFrameworkCore.Query.RelationalParameterBasedSqlProcessor.ExpandFromSqlParameter(SelectExpression selectExpression, IReadOnlyDictionary`2 parametersValues, Boolean& canCache)
at Microsoft.EntityFrameworkCore.Query.RelationalParameterBasedSqlProcessor.Optimize(SelectExpression selectExpression, IReadOnlyDictionary`2 parametersValues, Boolean& canCache)
at Microsoft.EntityFrameworkCore.SqlServer.Query.Internal.SqlServerParameterBasedSqlProcessor.Optimize(SelectExpression selectExpression, IReadOnlyDictionary`2 parametersValues, Boolean& canCache)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalCommandCache.GetRelationalCommandTemplate(IReadOnlyDictionary`2 parameters)
at Microsoft.EntityFrameworkCore.Internal.RelationCommandCacheExtensions.RentAndPopulateRelationalCommand(RelationalCommandCache relationalCommandCache, RelationalQueryContext queryContext)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.InitializeReader(Enumerator enumerator)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.<>c.<MoveNext>b__19_0(DbContext _, Enumerator enumerator)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()
at System.Linq.Enumerable.TryGetSingle[TSource](IEnumerable`1 source, Boolean& found)
at lambda_method4(Closure , QueryContext )
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
at System.Linq.Queryable.Any[TSource](IQueryable`1 source)
at async Program.<Initialize>(?) in :line 59
at Program.<Main>()

EF Core version: 6.0.0-rc.1.21452.10
Database provider: Microsoft.EntityFrameworkCore.SqlServer 6.0.0-rc.1.21452.10
Database: SQL Server 12.0.2000.8 (Azure SQL Database )
Target framework: .NET 6.0.100-rc.1.21458.32
Operating system: Windows 10

@smitpatel
Copy link
Contributor

Pollution of FromSqlParameterExpandingExpressionVisitor. Perhaps empty parameter list is throwing off the logic.

@ajcvickers
Copy link
Member

@smitpatel and/or @roji Can one of you take a look at this for 6.0.

@ajcvickers ajcvickers added this to the 6.0.0 milestone Sep 28, 2021
@smitpatel
Copy link
Contributor

Issue is that the SelectExpression with FromSql doesn't have any projection so we in-place mutate and the cache is polluted with modification. Our logic for in-place mutation is dependent on projection atm. Changing that logic could be risky. A way to fix without changing current logic would involve putting a hack with new internal API to avoid in-place mutation.
The issue happens with Any only and same logic existed in previous versions the same.

@smitpatel smitpatel removed this from the 6.0.0 milestone Sep 28, 2021
@ajcvickers ajcvickers added this to the 6.0.0 milestone Sep 29, 2021
@ajcvickers
Copy link
Member

Note from triage: we should at least throw better exception and point to workaround if other options are too risky for 6.0.

@smitpatel
Copy link
Contributor

#26532 will resolve this.

smitpatel added a commit that referenced this issue Dec 15, 2021
…pplied

- Add an internal state to remember the mutability which is set to false after ApplyProjection is called.
- Add overload of ApplyProjection which ignores shaper to create an immutable select expression to be used as subquery
- Add debug check to verify that all SelectExpression are marked as immutable
- Clone mapped projection of SqlExpression kind before translating it further to avoid reference sharing with projection which may be applied at later stage

Resolves #26532 - all those expressions have debug check in ctor
Resolves #26167 - by having more accurate flag for immutability
Resolves #26104 - by cloning the projection before translating further. This issue may get resolved in other way after pending selector work if we reuse projections from subquery but regardless the change seems better to avoid reference sharing of SelectExpression objects
@smitpatel smitpatel added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Dec 15, 2021
smitpatel added a commit that referenced this issue Dec 15, 2021
…pplied

- Add an internal state to remember the mutability which is set to false after ApplyProjection is called.
- Add overload of ApplyProjection which ignores shaper to create an immutable select expression to be used as subquery
- Add debug check to verify that all SelectExpression are marked as immutable
- Clone mapped projection of SqlExpression kind before translating it further to avoid reference sharing with projection which may be applied at later stage

Resolves #26532 - all those expressions have debug check in ctor
Resolves #26167 - by having more accurate flag for immutability
Resolves #26104 - by cloning the projection before translating further. This issue may get resolved in other way after pending selector work if we reuse projections from subquery but regardless the change seems better to avoid reference sharing of SelectExpression objects
smitpatel added a commit that referenced this issue Dec 15, 2021
…pplied

- Add an internal state to remember the mutability which is set to false after ApplyProjection is called.
- Add overload of ApplyProjection which ignores shaper to create an immutable select expression to be used as subquery
- Add debug check to verify that all SelectExpression are marked as immutable

Resolves #26532 - all those expressions have debug check in ctor
Resolves #26167 - by having more accurate flag for immutability
smitpatel added a commit that referenced this issue Jan 20, 2022
…pplied

- Add an internal state to remember the mutability which is set to false after ApplyProjection is called.
- Add overload of ApplyProjection which ignores shaper to create an immutable select expression to be used as subquery
- Add debug check to verify that all SelectExpression are marked as immutable

Resolves #26532 - all those expressions have debug check in ctor
Resolves #26167 - by having more accurate flag for immutability
smitpatel added a commit that referenced this issue Jan 20, 2022
…pplied (#27011)

- Add an internal state to remember the mutability which is set to false after ApplyProjection is called.
- Add overload of ApplyProjection which ignores shaper to create an immutable select expression to be used as subquery
- Add debug check to verify that all SelectExpression are marked as immutable

Resolves #26532 - all those expressions have debug check in ctor
Resolves #26167 - by having more accurate flag for immutability
@ajcvickers ajcvickers modified the milestones: 7.0.0, 7.0.0-preview1 Feb 14, 2022
@ajcvickers ajcvickers modified the milestones: 7.0.0-preview1, 7.0.0 Nov 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-query closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported priority-bug Issues which requires API breaks and have bigger impact hence should be fixed earlier in the release type-bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants