Skip to content

Commit

Permalink
Merge branch 'release/6.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
ajcvickers committed Nov 16, 2021
2 parents d3f69db + 6fc3e17 commit 1c2c60c
Show file tree
Hide file tree
Showing 25 changed files with 427 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Microsoft.EntityFrameworkCore.ChangeTracking.Internal;
using Microsoft.EntityFrameworkCore.Cosmos.Internal;
using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
Expand Down Expand Up @@ -39,6 +40,10 @@ private static readonly MethodInfo _jTokenToObjectMethodInfo
= typeof(JToken).GetRuntimeMethods()
.Single(mi => mi.Name == nameof(JToken.ToObject) && mi.GetParameters().Length == 0);

private static readonly MethodInfo _jTokenToObjectWithSerializerMethodInfo
= typeof(JToken).GetRuntimeMethods()
.Single(mi => mi.Name == nameof(JToken.ToObject) && mi.GetParameters().Length == 1 && mi.IsGenericMethodDefinition);

private static readonly MethodInfo _collectionAccessorAddMethodInfo
= typeof(IClrCollectionAccessor).GetTypeInfo()
.GetDeclaredMethod(nameof(IClrCollectionAccessor.Add));
Expand All @@ -65,16 +70,23 @@ private readonly IDictionary<Expression, Expression> _ordinalParameterBindings
private List<IncludeExpression> _pendingIncludes
= new();

private readonly bool _useOldBehavior;

private static readonly MethodInfo _toObjectMethodInfo
= typeof(CosmosProjectionBindingRemovingExpressionVisitorBase)
.GetRuntimeMethods().Single(mi => mi.Name == nameof(SafeToObject));

private static readonly MethodInfo _toObjectWithSerializerMethodInfo
= typeof(CosmosProjectionBindingRemovingExpressionVisitorBase)
.GetRuntimeMethods().Single(mi => mi.Name == nameof(SafeToObjectWithSerializer));

public CosmosProjectionBindingRemovingExpressionVisitorBase(
ParameterExpression jObjectParameter,
bool trackQueryResults)
{
_jObjectParameter = jObjectParameter;
_trackQueryResults = trackQueryResults;
_useOldBehavior = AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue26690", out var enabled) && enabled;
}

protected override Expression VisitBinary(BinaryExpression binaryExpression)
Expand Down Expand Up @@ -698,9 +710,14 @@ private Expression CreateGetValueExpression(
var body
= ReplacingExpressionVisitor.Replace(
converter.ConvertFromProviderExpression.Parameters.Single(),
Expression.Call(
jTokenParameter,
_jTokenToObjectMethodInfo.MakeGenericMethod(converter.ProviderClrType)),
_useOldBehavior
? Expression.Call(
jTokenParameter,
_jTokenToObjectMethodInfo.MakeGenericMethod(converter.ProviderClrType))
: Expression.Call(
jTokenParameter,
_jTokenToObjectWithSerializerMethodInfo.MakeGenericMethod(converter.ProviderClrType),
Expression.Constant(CosmosClientWrapper.Serializer)),
converter.ConvertFromProviderExpression.Body);

if (body.Type != type)
Expand Down Expand Up @@ -754,11 +771,16 @@ private Expression ConvertJTokenToType(Expression jTokenExpression, Type type)
=> type == typeof(JToken)
? jTokenExpression
: Expression.Call(
_toObjectMethodInfo.MakeGenericMethod(type),
_useOldBehavior
? _toObjectMethodInfo.MakeGenericMethod(type)
: _toObjectWithSerializerMethodInfo.MakeGenericMethod(type),
jTokenExpression);

private static T SafeToObject<T>(JToken token)
=> token == null || token.Type == JTokenType.Null ? default : token.ToObject<T>();

private static T SafeToObjectWithSerializer<T>(JToken token)
=> token == null || token.Type == JTokenType.Null ? default : token.ToObject<T>(CosmosClientWrapper.Serializer);
}
}
}
21 changes: 18 additions & 3 deletions src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2620,6 +2620,18 @@ private SqlRemappingVisitor PushdownIntoSubqueryInternal()
_tables.Add(subquery);
_tableReferences.Add(subqueryTableReferenceExpression);

var useOldBehavior = AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue26587", out var enabled)
&& enabled;

if (!useOldBehavior)
{
// Remap tableReferences in inner so that all components follow referential integrity.
foreach (var tableReference in subquery._tableReferences)
{
tableReference.UpdateTableReference(this, subquery);
}
}

var projectionMap = new Dictionary<SqlExpression, ColumnExpression>(ReferenceEqualityComparer.Instance);

if (_projection.Count > 0)
Expand Down Expand Up @@ -2756,10 +2768,13 @@ private SqlRemappingVisitor PushdownIntoSubqueryInternal()
subquery.ClearOrdering();
}

// Remap tableReferences in inner
foreach (var tableReference in subquery._tableReferences)
if (useOldBehavior)
{
tableReference.UpdateTableReference(this, subquery);
// Remap tableReferences in inner
foreach (var tableReference in subquery._tableReferences)
{
tableReference.UpdateTableReference(this, subquery);
}
}

var tableReferenceUpdatingExpressionVisitor = new TableReferenceUpdatingExpressionVisitor(this, subquery);
Expand Down
49 changes: 47 additions & 2 deletions src/EFCore/Metadata/Internal/Property.cs
Original file line number Diff line number Diff line change
Expand Up @@ -826,9 +826,18 @@ public virtual CoreTypeMapping? TypeMapping
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual ValueComparer? GetValueComparer()
=> (ValueComparer?)this[CoreAnnotationNames.ValueComparer]
{
if (!(AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue26629", out var enabled)
&& enabled))
{
return GetValueComparer(new HashSet<IProperty>())
?? TypeMapping?.Comparer;
}

return (ValueComparer?)this[CoreAnnotationNames.ValueComparer]
?? FindFirstDifferentPrincipal()?.GetValueComparer()
?? TypeMapping?.Comparer;
}

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
Expand All @@ -837,9 +846,45 @@ public virtual CoreTypeMapping? TypeMapping
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual ValueComparer? GetKeyValueComparer()
=> (ValueComparer?)this[CoreAnnotationNames.ValueComparer]
{
if (!(AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue26629", out var enabled)
&& enabled))
{
return GetValueComparer(new HashSet<IProperty>())
?? TypeMapping?.KeyComparer;
}

return (ValueComparer?)this[CoreAnnotationNames.ValueComparer]
?? FindFirstDifferentPrincipal()?.GetKeyValueComparer()
?? TypeMapping?.KeyComparer;
}

private ValueComparer? GetValueComparer(HashSet<IProperty>? checkedProperties)
{
var comparer = (ValueComparer?)this[CoreAnnotationNames.ValueComparer];
if (comparer != null)
{
return comparer;
}

var principal = ((Property?)FindFirstDifferentPrincipal());
if (principal == null)
{
return null;
}

if (checkedProperties == null)
{
checkedProperties = new();
}
else if (checkedProperties.Contains(this))
{
return null;
}

checkedProperties.Add(this);
return principal.GetValueComparer(checkedProperties);
}

private IProperty? FindFirstDifferentPrincipal()
{
Expand Down
118 changes: 100 additions & 18 deletions src/Microsoft.Data.Sqlite.Core/SqliteConnectionFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,25 @@ internal class SqliteConnectionFactory
{
public static readonly SqliteConnectionFactory Instance = new();

private readonly bool _newLockingBehavior;
#pragma warning disable IDE0052 // Remove unread private members
private readonly Timer _pruneTimer;
#pragma warning restore IDE0052 // Remove unread private members
private readonly List<SqliteConnectionPoolGroup> _idlePoolGroups = new();
private readonly List<SqliteConnectionPool> _poolsToRelease = new();
private readonly ReaderWriterLockSlim _lock = new();

private Dictionary<string, SqliteConnectionPoolGroup> _poolGroups = new();

protected SqliteConnectionFactory()
{
AppDomain.CurrentDomain.DomainUnload += (_, _) => ClearPools();
AppDomain.CurrentDomain.ProcessExit += (_, _) => ClearPools();
_newLockingBehavior = !AppContext.TryGetSwitch("Microsoft.Data.Sqlite.Issue26612", out var enabled) || !enabled;

if (!AppContext.TryGetSwitch("Microsoft.Data.Sqlite.Issue26422", out enabled) || !enabled)
{
AppDomain.CurrentDomain.DomainUnload += (_, _) => ClearPools();
AppDomain.CurrentDomain.ProcessExit += (_, _) => ClearPools();
}

_pruneTimer = new Timer(PruneCallback, null, TimeSpan.FromMinutes(4), TimeSpan.FromSeconds(30));
}
Expand All @@ -49,28 +56,63 @@ public SqliteConnectionInternal GetConnection(SqliteConnection outerConnection)

public SqliteConnectionPoolGroup GetPoolGroup(string connectionString)
{
if (!_poolGroups.TryGetValue(connectionString, out var poolGroup)
|| (poolGroup.IsDisabled
&& !poolGroup.IsNonPooled))
if (_newLockingBehavior)
{
var connectionOptions = new SqliteConnectionStringBuilder(connectionString);
_lock.EnterUpgradeableReadLock();
}

lock (this)
try
{
if (!_poolGroups.TryGetValue(connectionString, out var poolGroup)
|| (poolGroup.IsDisabled
&& !poolGroup.IsNonPooled))
{
if (!_poolGroups.TryGetValue(connectionString, out poolGroup))
var connectionOptions = new SqliteConnectionStringBuilder(connectionString);

if (_newLockingBehavior)
{
var isNonPooled = connectionOptions.DataSource == ":memory:"
|| connectionOptions.Mode == SqliteOpenMode.Memory
|| connectionOptions.DataSource.Length == 0
|| !connectionOptions.Pooling;
_lock.EnterWriteLock();
}
else
{
Monitor.Enter(this);
}

poolGroup = new SqliteConnectionPoolGroup(connectionOptions, connectionString, isNonPooled);
_poolGroups.Add(connectionString, poolGroup);
try
{
if (!_poolGroups.TryGetValue(connectionString, out poolGroup))
{
var isNonPooled = connectionOptions.DataSource == ":memory:"
|| connectionOptions.Mode == SqliteOpenMode.Memory
|| connectionOptions.DataSource.Length == 0
|| !connectionOptions.Pooling;

poolGroup = new SqliteConnectionPoolGroup(connectionOptions, connectionString, isNonPooled);
_poolGroups.Add(connectionString, poolGroup);
}
}
finally
{
if (_newLockingBehavior)
{
_lock.ExitWriteLock();
}
else
{
Monitor.Exit(this);
}
}
}
}

return poolGroup;
return poolGroup;
}
finally
{
if (_newLockingBehavior)
{
_lock.ExitUpgradeableReadLock();
}
}
}

public void ReleasePool(SqliteConnectionPool pool, bool clearing)
Expand All @@ -90,13 +132,33 @@ public void ReleasePool(SqliteConnectionPool pool, bool clearing)

public void ClearPools()
{
lock (this)
if (_newLockingBehavior)
{
_lock.EnterWriteLock();
}
else
{
Monitor.Enter(this);
}

try
{
foreach (var entry in _poolGroups)
{
entry.Value.Clear();
}
}
finally
{
if (_newLockingBehavior)
{
_lock.ExitWriteLock();
}
else
{
Monitor.Exit(this);
}
}
}

private void PruneCallback(object? _)
Expand Down Expand Up @@ -126,7 +188,16 @@ private void PruneCallback(object? _)
}
}

lock (this)
if (_newLockingBehavior)
{
_lock.EnterWriteLock();
}
else
{
Monitor.Enter(this);
}

try
{
var activePoolGroups = new Dictionary<string, SqliteConnectionPoolGroup>();
foreach (var entry in _poolGroups)
Expand All @@ -145,6 +216,17 @@ private void PruneCallback(object? _)

_poolGroups = activePoolGroups;
}
finally
{
if (_newLockingBehavior)
{
_lock.ExitWriteLock();
}
else
{
Monitor.Exit(this);
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ public TestSqlLoggerFactory TestSqlLoggerFactory
public override DateTime DefaultDateTime
=> new();

public override bool PreservesDateTimeKind
=> true;

protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context)
{
base.OnModelCreating(modelBuilder, context);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,9 @@ public override bool SupportsDecimalComparisons
public override DateTime DefaultDateTime
=> new();

public override bool PreservesDateTimeKind
=> true;

public TestSqlLoggerFactory TestSqlLoggerFactory
=> (TestSqlLoggerFactory)ListLoggerFactory;

Expand Down
3 changes: 0 additions & 3 deletions test/EFCore.Cosmos.FunctionalTests/EndToEndCosmosTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,11 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos;
using Microsoft.Azure.Cosmos.Serialization.HybridRow;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Cosmos.ChangeTracking.Internal;
using Microsoft.EntityFrameworkCore.Cosmos.Internal;
using Microsoft.EntityFrameworkCore.Diagnostics.Internal;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata.Conventions;
using Microsoft.EntityFrameworkCore.TestUtilities;
Expand Down
Loading

0 comments on commit 1c2c60c

Please sign in to comment.