Skip to content

Commit

Permalink
Adjusted some tests and added a fix for regression in EF Core (dotnet…
Browse files Browse the repository at this point in the history
  • Loading branch information
PawelGerr committed Nov 11, 2020
1 parent cc8a484 commit 0b4dec1
Show file tree
Hide file tree
Showing 13 changed files with 231 additions and 17 deletions.
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<RepositoryUrl>https://[email protected]/pawelgerr/Thinktecture.EntityFrameworkCore/_git/Thinktecture.EntityFrameworkCore</RepositoryUrl>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<RootNamespace>Thinktecture</RootNamespace>
<LangVersion>8.0</LangVersion>
<LangVersion>9.0</LangVersion>
<Nullable>enable</Nullable>
<NoWarn>$(NoWarn);CA1303</NoWarn>
</PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ private static EntityTypeBuilder<T> Configure<T>(this ModelBuilder modelBuilder,

var tableName = "#" + typeof(T).ShortDisplayName();

var builder = modelBuilder.Entity<T>().ToView(tableName);
var builder = modelBuilder.Entity<T>().ToTable(tableName);

if (isKeyless)
builder.HasNoKey();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;

namespace Thinktecture.EntityFrameworkCore.Infrastructure
{
Expand Down Expand Up @@ -28,7 +29,19 @@ public void Customize(ModelBuilder modelBuilder, DbContext context)
_modelCustomizer.Customize(modelBuilder, context);

if (context is IDbDefaultSchema schema && schema.Schema != null)
{
modelBuilder.HasDefaultSchema(schema.Schema);

// fix for regression: https://github.com/dotnet/efcore/issues/23274
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
if (entityType.GetViewName() is not null &&
entityType.FindAnnotation(RelationalAnnotationNames.ViewSchema) is { Value: null })
{
entityType.SetViewSchema(schema.Schema);
}
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,18 @@ public bool AddCustomRelationalQueryContextFactory
set => _addCustomRelationalQueryContextFactory = value;
}

private bool _addCustomRelationalParameterBasedSqlProcessorFactory;

/// <summary>
/// A custom factory is registered if <c>true</c>.
/// The factory is required for some features.
/// </summary>
public bool AddCustomRelationalParameterBasedSqlProcessorFactory
{
get => _addCustomRelationalParameterBasedSqlProcessorFactory || AddRowNumberSupport || AddCountDistinctSupport;
set => _addCustomRelationalParameterBasedSqlProcessorFactory = value;
}

/// <summary>
/// Initializes new instance of <see cref="RelationalDbContextOptionsExtension"/>.
/// </summary>
Expand Down Expand Up @@ -264,6 +276,7 @@ private class RelationalDbContextOptionsExtensionInfo : DbContextOptionsExtensio
'Custom RelationalQueryContextFactory'={_extension.AddCustomRelationalQueryContextFactory},
'Custom QueryableMethodTranslatingExpressionVisitorFactory'={_extension.AddCustomQueryableMethodTranslatingExpressionVisitorFactory},
'Custom RelationalSqlTranslatingExpressionVisitorFactory'={_extension.AddCustomRelationalSqlTranslatingExpressionVisitorFactory},
'Custom RelationalParameterBasedSqlProcessorFactory'={_extension.AddCustomRelationalParameterBasedSqlProcessorFactory},
'Custom QuerySqlGeneratorFactory'={_extension.AddCustomQuerySqlGeneratorFactory},
'Default schema respecting components added'={_extension.AddSchemaRespectingComponents},
'NestedTransactionsSupport'={_extension.AddNestedTransactionsSupport},
Expand Down Expand Up @@ -293,8 +306,9 @@ public override long GetServiceProviderHashCode()
_extension._serviceDescriptors.ForEach(descriptor => hashCode.Add(GetHashCode(descriptor)));

// Following switches doesn't add any new components:
// AddRowNumberSupport, AddCountDistinctSupport, AddTenantDatabaseSupport,
// AddCustomRelationalSqlTranslatingExpressionVisitorFactory, AddCustomQuerySqlGeneratorFactory
// AddRowNumberSupport, AddCountDistinctSupport, AddTenantDatabaseSupport,
// AddCustomRelationalSqlTranslatingExpressionVisitorFactory, AddCustomQuerySqlGeneratorFactory,
// AddCustomRelationalParameterBasedSqlProcessorFactory

return hashCode.ToHashCode();
}
Expand Down Expand Up @@ -325,6 +339,7 @@ public override void PopulateDebugInfo(IDictionary<string, string> debugInfo)
debugInfo["Thinktecture:CustomRelationalQueryContextFactory"] = _extension.AddCustomRelationalQueryContextFactory.ToString(CultureInfo.InvariantCulture);
debugInfo["Thinktecture:CustomQueryableMethodTranslatingExpressionVisitorFactory"] = _extension.AddCustomQueryableMethodTranslatingExpressionVisitorFactory.ToString(CultureInfo.InvariantCulture);
debugInfo["Thinktecture:CustomRelationalSqlTranslatingExpressionVisitorFactory"] = _extension.AddCustomRelationalSqlTranslatingExpressionVisitorFactory.ToString(CultureInfo.InvariantCulture);
debugInfo["Thinktecture:CustomRelationalParameterBasedSqlProcessorFactory"] = _extension.AddCustomRelationalParameterBasedSqlProcessorFactory.ToString(CultureInfo.InvariantCulture);
debugInfo["Thinktecture:CustomQuerySqlGeneratorFactory"] = _extension.AddCustomQuerySqlGeneratorFactory.ToString(CultureInfo.InvariantCulture);
debugInfo["Thinktecture:SchemaRespectingComponents"] = _extension.AddSchemaRespectingComponents.ToString(CultureInfo.InvariantCulture);
debugInfo["Thinktecture:NestedTransactionsSupport"] = _extension.AddNestedTransactionsSupport.ToString(CultureInfo.InvariantCulture);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Thinktecture.EntityFrameworkCore.Query.SqlExpressions
/// </summary>
public class CountDistinctExpression : SqlExpression
{
private readonly SqlExpression _column;
public SqlExpression Column { get; }

/// <summary>
/// Initializes new instance of <see cref="CountDistinctExpression"/>.
Expand All @@ -22,7 +22,7 @@ public class CountDistinctExpression : SqlExpression
public CountDistinctExpression(SqlExpression column, RelationalTypeMapping typeMapping)
: base(typeof(int), typeMapping)
{
_column = column ?? throw new ArgumentNullException(nameof(column));
Column = column ?? throw new ArgumentNullException(nameof(column));
}

/// <inheritdoc />
Expand All @@ -32,20 +32,18 @@ protected override void Print(ExpressionPrinter expressionPrinter)
throw new ArgumentNullException(nameof(expressionPrinter));

expressionPrinter.Append("COUNT(DISTINCT ");
expressionPrinter.Visit(_column);
expressionPrinter.Visit(Column);
expressionPrinter.Append(")");
}

/// <inheritdoc />
protected override Expression VisitChildren(ExpressionVisitor visitor)
{
#pragma warning disable CA1062
var visitedColumn = visitor.Visit(_column);
var visitedColumn = visitor.Visit(Column);
#pragma warning restore CA1062

return ReferenceEquals(_column, visitedColumn)
? this
: new CountDistinctExpression((SqlExpression)visitedColumn, TypeMapping);
return Update((SqlExpression)visitedColumn);
}

/// <inheritdoc />
Expand All @@ -55,7 +53,7 @@ protected override Expression Accept(ExpressionVisitor visitor)
return base.Accept(visitor);

sqlGenerator.Visit(new SqlFragmentExpression("COUNT(DISTINCT "));
sqlGenerator.Visit(_column);
sqlGenerator.Visit(Column);
sqlGenerator.Visit(new SqlFragmentExpression(")"));

return this;
Expand All @@ -69,13 +67,20 @@ public override bool Equals(object obj)

private bool Equals(CountDistinctExpression? expression)
{
return base.Equals(expression) && _column.Equals(expression._column);
return base.Equals(expression) && Column.Equals(expression.Column);
}

/// <inheritdoc />
public override int GetHashCode()
{
return HashCode.Combine(base.GetHashCode(), _column);
return HashCode.Combine(base.GetHashCode(), Column);
}

public CountDistinctExpression Update(SqlExpression column)
{
return ReferenceEquals(Column, column)
? this
: new CountDistinctExpression(column, TypeMapping);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Query.SqlExpressions;

namespace Thinktecture.EntityFrameworkCore.Query
{
/// <summary>
/// Extends <see cref="RelationalParameterBasedSqlProcessor"/>.
/// </summary>
public class ThinktectureRelationalParameterBasedSqlProcessor : RelationalParameterBasedSqlProcessor
{
/// <inheritdoc />
public ThinktectureRelationalParameterBasedSqlProcessor(
RelationalParameterBasedSqlProcessorDependencies dependencies,
bool useRelationalNulls)
: base(dependencies, useRelationalNulls)
{
}

/// <inheritdoc />
protected override SelectExpression ProcessSqlNullability(SelectExpression selectExpression, IReadOnlyDictionary<string, object> parametersValues, out bool canCache)
{
if (selectExpression == null)
throw new ArgumentNullException(nameof(selectExpression));
if (parametersValues == null)
throw new ArgumentNullException(nameof(parametersValues));

return new ThinktectureSqlNullabilityProcessor(Dependencies, UseRelationalNulls).Process(selectExpression, parametersValues, out canCache);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using Microsoft.EntityFrameworkCore.Query;

namespace Thinktecture.EntityFrameworkCore.Query
{
/// <inheritdoc />
public class ThinktectureRelationalParameterBasedSqlProcessorFactory : IRelationalParameterBasedSqlProcessorFactory
{
private readonly RelationalParameterBasedSqlProcessorDependencies _dependencies;

/// <summary>
/// Initializes new instance of <see cref="ThinktectureRelationalParameterBasedSqlProcessorFactory"/>.
/// </summary>
/// <param name="dependencies">Dependencies.</param>
public ThinktectureRelationalParameterBasedSqlProcessorFactory(RelationalParameterBasedSqlProcessorDependencies dependencies)
{
_dependencies = dependencies;
}

/// <inheritdoc />
public RelationalParameterBasedSqlProcessor Create(bool useRelationalNulls)
{
return new ThinktectureRelationalParameterBasedSqlProcessor(_dependencies, useRelationalNulls);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Query.SqlExpressions;
using Thinktecture.EntityFrameworkCore.Query.SqlExpressions;

namespace Thinktecture.EntityFrameworkCore.Query
{
/// <summary>
/// Extends <see cref="SqlNullabilityProcessor"/>.
/// </summary>
public class ThinktectureSqlNullabilityProcessor : SqlNullabilityProcessor
{
/// <inheritdoc />
public ThinktectureSqlNullabilityProcessor(
RelationalParameterBasedSqlProcessorDependencies dependencies,
bool useRelationalNulls)
: base(dependencies, useRelationalNulls)
{
}

/// <inheritdoc />
protected override SqlExpression VisitCustomSqlExpression(SqlExpression sqlExpression, bool allowOptimizedExpansion, out bool nullable)
{
if (sqlExpression is RowNumberClauseOrderingsExpression)
{
nullable = false;
return sqlExpression;
}

if (sqlExpression is CountDistinctExpression countDistinctExpression)
{
var visitedExpression = Visit(countDistinctExpression.Column, allowOptimizedExpansion, out nullable);
nullable = false;
return countDistinctExpression.Update(visitedExpression);
}

return base.VisitCustomSqlExpression(sqlExpression, allowOptimizedExpansion, out nullable);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,16 @@ public bool AddCustomRelationalSqlTranslatingExpressionVisitorFactory
set => _relationalOptions.AddCustomRelationalSqlTranslatingExpressionVisitorFactory = value;
}

/// <summary>
/// A custom factory is registered if <c>true</c>.
/// The factory is required for some features.
/// </summary>
public bool AddCustomRelationalParameterBasedSqlProcessorFactory
{
get => _relationalOptions.AddCustomRelationalParameterBasedSqlProcessorFactory;
set => _relationalOptions.AddCustomRelationalParameterBasedSqlProcessorFactory = value;
}

/// <summary>
/// A custom factory is registered if <c>true</c>.
/// The factory is required for some features like 'tenant database support'.
Expand Down Expand Up @@ -129,6 +139,9 @@ public void ApplyServices(IServiceCollection services)
if (AddCustomRelationalSqlTranslatingExpressionVisitorFactory)
services.Add<IRelationalSqlTranslatingExpressionVisitorFactory, ThinktectureSqlServerSqlTranslatingExpressionVisitorFactory>(RelationalDbContextOptionsExtension.GetLifetime<IRelationalSqlTranslatingExpressionVisitorFactory>());

if (AddCustomRelationalParameterBasedSqlProcessorFactory)
services.Add<IRelationalParameterBasedSqlProcessorFactory, ThinktectureSqlServerParameterBasedSqlProcessorFactory>(RelationalDbContextOptionsExtension.GetLifetime<IRelationalParameterBasedSqlProcessorFactory>());

if (AddTempTableSupport)
{
services.TryAddScoped<ISqlServerTempTableCreator, SqlServerTempTableCreator>();
Expand Down Expand Up @@ -189,6 +202,7 @@ public override long GetServiceProviderHashCode()
{
return HashCode.Combine(_extension.AddCustomQuerySqlGeneratorFactory,
_extension.AddCustomRelationalSqlTranslatingExpressionVisitorFactory,
_extension.AddCustomRelationalParameterBasedSqlProcessorFactory,
_extension.AddBulkOperationSupport,
_extension.AddTempTableSupport,
_extension.UseThinktectureSqlServerMigrationsSqlGenerator);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Query.SqlExpressions;
using Microsoft.EntityFrameworkCore.SqlServer.Query.Internal;

namespace Thinktecture.EntityFrameworkCore.Query
{
[SuppressMessage("ReSharper", "EF1001")]
public class ThinktectureSqlServerParameterBasedSqlProcessor : SqlServerParameterBasedSqlProcessor
{
/// <inheritdoc />
public ThinktectureSqlServerParameterBasedSqlProcessor(RelationalParameterBasedSqlProcessorDependencies dependencies, bool useRelationalNulls)
: base(dependencies, useRelationalNulls)
{
}

/// <inheritdoc />
protected override SelectExpression ProcessSqlNullability(SelectExpression selectExpression, IReadOnlyDictionary<string, object> parametersValues, out bool canCache)
{
if (selectExpression == null)
throw new ArgumentNullException(nameof(selectExpression));
if (parametersValues == null)
throw new ArgumentNullException(nameof(parametersValues));

return new ThinktectureSqlNullabilityProcessor(Dependencies, UseRelationalNulls).Process(selectExpression, parametersValues, out canCache);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System.Diagnostics.CodeAnalysis;
using Microsoft.EntityFrameworkCore.Query;

namespace Thinktecture.EntityFrameworkCore.Query
{
/// <inheritdoc />
[SuppressMessage("ReSharper", "EF1001")]
public class ThinktectureSqlServerParameterBasedSqlProcessorFactory : IRelationalParameterBasedSqlProcessorFactory
{
private readonly RelationalParameterBasedSqlProcessorDependencies _dependencies;

/// <summary>
/// Initializes <see cref="ThinktectureSqlServerParameterBasedSqlProcessorFactory"/>.
/// </summary>
/// <param name="dependencies">Dependencies.</param>
public ThinktectureSqlServerParameterBasedSqlProcessorFactory(RelationalParameterBasedSqlProcessorDependencies dependencies)
{
_dependencies = dependencies;
}

/// <inheritdoc />
public RelationalParameterBasedSqlProcessor Create(bool useRelationalNulls)
{
return new ThinktectureSqlServerParameterBasedSqlProcessor(_dependencies, useRelationalNulls);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,16 @@ public bool AddCustomRelationalSqlTranslatingExpressionVisitorFactory
set => _relationalOptions.AddCustomRelationalSqlTranslatingExpressionVisitorFactory = value;
}

/// <summary>
/// A custom factory is registered if <c>true</c>.
/// The factory is required for some features.
/// </summary>
public bool AddCustomRelationalParameterBasedSqlProcessorFactory
{
get => _relationalOptions.AddCustomRelationalParameterBasedSqlProcessorFactory;
set => _relationalOptions.AddCustomRelationalParameterBasedSqlProcessorFactory = value;
}

/// <summary>
/// Enables and disables support for temp tables.
/// </summary>
Expand Down Expand Up @@ -100,6 +110,9 @@ public void ApplyServices(IServiceCollection services)
if (AddCustomRelationalSqlTranslatingExpressionVisitorFactory)
services.Add<IRelationalSqlTranslatingExpressionVisitorFactory, ThinktectureSqliteSqlTranslatingExpressionVisitorFactory>(GetLifetime<IRelationalSqlTranslatingExpressionVisitorFactory>());

if(AddCustomRelationalParameterBasedSqlProcessorFactory)
services.Add<IRelationalParameterBasedSqlProcessorFactory, ThinktectureRelationalParameterBasedSqlProcessorFactory>(GetLifetime<IRelationalParameterBasedSqlProcessorFactory>());

if (AddTempTableSupport)
{
services.TryAddScoped<ITempTableCreator, SqliteTempTableCreator>();
Expand Down Expand Up @@ -150,6 +163,7 @@ public override long GetServiceProviderHashCode()
{
return HashCode.Combine(_extension.AddCustomQueryableMethodTranslatingExpressionVisitorFactory,
_extension.AddCustomRelationalSqlTranslatingExpressionVisitorFactory,
_extension.AddCustomRelationalParameterBasedSqlProcessorFactory,
_extension.AddBulkOperationSupport,
_extension.AddTempTableSupport);
}
Expand Down
Loading

0 comments on commit 0b4dec1

Please sign in to comment.