Skip to content

Commit

Permalink
Merge branch 'release/7.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
ajcvickers committed Sep 15, 2022
2 parents 235507f + 5d0d937 commit 53db832
Show file tree
Hide file tree
Showing 211 changed files with 6,855 additions and 2,564 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="$(SqlitePCLRawVersion)" />
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.1" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Specialized;
using System.Diagnostics.CodeAnalysis;
using Microsoft.EntityFrameworkCore.Utilities;

namespace Microsoft.EntityFrameworkCore.ChangeTracking.Internal;
Expand All @@ -12,6 +13,8 @@ namespace Microsoft.EntityFrameworkCore.ChangeTracking.Internal;
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
[RequiresUnreferencedCode(
"BindingList raises ListChanged events with PropertyDescriptors. PropertyDescriptors require unreferenced code.")]
public class ObservableBackedBindingList<T> : SortableBindingList<T>
{
private bool _addingNewInstance;
Expand All @@ -28,6 +31,8 @@ public class ObservableBackedBindingList<T> : SortableBindingList<T>
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
[RequiresUnreferencedCode(
"BindingList raises ListChanged events with PropertyDescriptors. PropertyDescriptors require unreferenced code.")]
public ObservableBackedBindingList(ICollection<T> observableCollection)
: base(observableCollection.ToList())
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.Collections;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;

namespace Microsoft.EntityFrameworkCore.ChangeTracking.Internal;

Expand All @@ -12,6 +13,7 @@ namespace Microsoft.EntityFrameworkCore.ChangeTracking.Internal;
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
[RequiresUnreferencedCode("Raises ListChanged events with PropertyDescriptors. PropertyDescriptors require unreferenced code.")]
public class SortableBindingList<T> : BindingList<T>
{
private bool _isSorted;
Expand All @@ -24,6 +26,7 @@ public class SortableBindingList<T> : BindingList<T>
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
[RequiresUnreferencedCode("Raises ListChanged events with PropertyDescriptors. PropertyDescriptors require unreferenced code.")]
public SortableBindingList(List<T> list)
: base(list)
{
Expand All @@ -35,6 +38,13 @@ public SortableBindingList(List<T> list)
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
[RequiresUnreferencedCode("Requires accessing property 'Default' on the property descriptor's type")]
[UnconditionalSuppressMessage(
"ReflectionAnalysis",
"IL2046",
Justification =
"This method is an override, and the base method isn't annotated with RequiresUnreferencedCode. " +
"The entire type is marked with RequiresUnreferencedCode.")]
protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
{
if (PropertyComparer.CanSort(prop.PropertyType))
Expand Down Expand Up @@ -101,6 +111,7 @@ private sealed class PropertyComparer : Comparer<T>
private readonly ListSortDirection _direction;
private readonly PropertyDescriptor _prop;

[RequiresUnreferencedCode("Requires accessing property 'Default' on the property descriptor's type")]
public PropertyComparer(PropertyDescriptor prop, ListSortDirection direction)
{
if (!prop.ComponentType.IsAssignableFrom(typeof(T)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Collections;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;

namespace Microsoft.EntityFrameworkCore.ChangeTracking;

Expand All @@ -25,6 +26,8 @@ namespace Microsoft.EntityFrameworkCore.ChangeTracking;
/// </para>
/// </remarks>
/// <typeparam name="T">The type of elements in the collection.</typeparam>
[RequiresUnreferencedCode(
"BindingList raises ListChanged events with PropertyDescriptors. PropertyDescriptors require unreferenced code.")]
public class ObservableCollectionListSource<T> : ObservableCollection<T>, IListSource
where T : class
{
Expand Down Expand Up @@ -71,6 +74,14 @@ bool IListSource.ContainsListCollection
/// <returns>
/// An <see cref="IBindingList" /> in sync with the ObservableCollection.
/// </returns>
[RequiresUnreferencedCode(
"BindingList raises ListChanged events with PropertyDescriptors. PropertyDescriptors require unreferenced code.")]
[UnconditionalSuppressMessage(
"ReflectionAnalysis",
"IL2046",
Justification =
"This method is an interface implementation, and the interface method isn't annotated with RequiresUnreferencedCode. " +
"The entire type is marked with RequiresUnreferencedCode.")]
IList IListSource.GetList()
=> _bindingList ??= this.ToBindingList();
}
2 changes: 2 additions & 0 deletions src/EFCore.Abstractions/EntityTypeConfigurationAttribute.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics.CodeAnalysis;
using Microsoft.EntityFrameworkCore.Utilities;

namespace Microsoft.EntityFrameworkCore;
Expand Down Expand Up @@ -28,5 +29,6 @@ public EntityTypeConfigurationAttribute(Type entityConfigurationType)
/// <summary>
/// Type of the entity type configuration.
/// </summary>
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.Interfaces)]
public Type EntityTypeConfigurationType { get; }
}
3 changes: 3 additions & 0 deletions src/EFCore.Abstractions/ObservableCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using Microsoft.EntityFrameworkCore.ChangeTracking.Internal;

namespace Microsoft.EntityFrameworkCore;
Expand All @@ -23,6 +24,8 @@ public static class ObservableCollectionExtensions
/// <typeparam name="T">The element type.</typeparam>
/// <param name="source">The collection that the binding list will stay in sync with.</param>
/// <returns>The binding list.</returns>
[RequiresUnreferencedCode(
"BindingList raises ListChanged events with PropertyDescriptors. PropertyDescriptors require unreferenced code.")]
public static BindingList<T> ToBindingList<T>(this ObservableCollection<T> source)
where T : class
=> new ObservableBackedBindingList<T>(source);
Expand Down
1 change: 0 additions & 1 deletion src/EFCore.Analyzers/EFCore.Analyzers.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
</ItemGroup>

<ItemGroup>
<!-- NB: Version affects the minimum required Visual Studio version -->
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="$(MicrosoftCodeAnalysisVersion)" PrivateAssets="all" />
<PackageReference Update="NETStandard.Library" PrivateAssets="all" />
</ItemGroup>
Expand Down
2 changes: 2 additions & 0 deletions src/EFCore.Cosmos/Storage/Internal/CosmosDatabaseWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ public override int SaveChanges(IList<IUpdateEntry> entries)
// #16707
((InternalEntityEntry)root).SetEntityState(EntityState.Modified);
#pragma warning restore EF1001 // Internal EF Core API usage.
entries.Add(root);
}

continue;
Expand Down Expand Up @@ -151,6 +152,7 @@ public override async Task<int> SaveChangesAsync(
// #16707
((InternalEntityEntry)root).SetEntityState(EntityState.Modified);
#pragma warning restore EF1001 // Internal EF Core API usage.
entries.Add(root);
}

continue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,7 @@ private void Create(
property.DeclaringEntityType.ShortName(), property.Name, nameof(PropertyBuilder.HasConversion)));
}

var valueConverterType = (Type?)property[CoreAnnotationNames.ValueConverterType];
var valueConverterType = GetValueConverterType(property);
if (valueConverterType == null
&& property.GetValueConverter() != null)
{
Expand Down Expand Up @@ -847,6 +847,45 @@ private void Create(
mainBuilder.AppendLine();
}

private static Type? GetValueConverterType(IProperty property)
{
var type = (Type?)property[CoreAnnotationNames.ValueConverterType];
if (type != null)
{
return type;
}

var principalProperty = property;
for (var i = 0; i < 10000; i++)
{
foreach (var foreignKey in principalProperty.GetContainingForeignKeys())
{
for (var propertyIndex = 0; propertyIndex < foreignKey.Properties.Count; propertyIndex++)
{
if (principalProperty == foreignKey.Properties[propertyIndex])
{
var newPrincipalProperty = foreignKey.PrincipalKey.Properties[propertyIndex];
if (property == principalProperty
|| newPrincipalProperty == principalProperty)
{
break;
}

principalProperty = newPrincipalProperty;

type = (Type?)principalProperty[CoreAnnotationNames.ValueConverterType];
if (type != null)
{
return type;
}
}
}
}
}

return null;
}

private void PropertyBaseParameters(
IPropertyBase property,
CSharpRuntimeAnnotationCodeGeneratorParameters parameters,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public static IServiceCollection AddEntityFrameworkInMemoryDatabase(this IServic
.TryAdd<ITypeMappingSource, InMemoryTypeMappingSource>()
.TryAdd<IShapedQueryCompilingExpressionVisitorFactory, InMemoryShapedQueryCompilingExpressionVisitorFactory>()
.TryAdd<IQueryableMethodTranslatingExpressionVisitorFactory, InMemoryQueryableMethodTranslatingExpressionVisitorFactory>()
.TryAdd<IQueryTranslationPreprocessorFactory, InMemoryQueryTranslationPreprocessorFactory>()
.TryAdd<ISingletonOptions, IInMemorySingletonOptions>(p => p.GetRequiredService<IInMemorySingletonOptions>())
.TryAddProviderSpecificServices(
b => b
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,11 @@ public override string LogFragment

builder.Append("StoreName=").Append(Extension._storeName).Append(' ');

if (!Extension._nullabilityCheckEnabled)
{
builder.Append("NullabilityChecksEnabled ");
}

_logFragment = builder.ToString();
}

Expand All @@ -183,14 +188,24 @@ public override string LogFragment
}

public override int GetServiceProviderHashCode()
=> Extension._databaseRoot?.GetHashCode() ?? 0;
{
var hashCode = new HashCode();
hashCode.Add(Extension._databaseRoot);
hashCode.Add(Extension._nullabilityCheckEnabled);
return hashCode.ToHashCode();
}

public override bool ShouldUseSameServiceProvider(DbContextOptionsExtensionInfo other)
=> other is ExtensionInfo otherInfo
&& Extension._databaseRoot == otherInfo.Extension._databaseRoot;
&& Extension._databaseRoot == otherInfo.Extension._databaseRoot
&& Extension._nullabilityCheckEnabled == otherInfo.Extension._nullabilityCheckEnabled;

public override void PopulateDebugInfo(IDictionary<string, string> debugInfo)
=> debugInfo["InMemoryDatabase:DatabaseRoot"]
{
debugInfo["InMemoryDatabase:DatabaseRoot"]
= (Extension._databaseRoot?.GetHashCode() ?? 0).ToString(CultureInfo.InvariantCulture);
debugInfo["InMemoryDatabase:NullabilityChecksEnabled"]
= (!Extension._nullabilityCheckEnabled).GetHashCode().ToString(CultureInfo.InvariantCulture);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ public virtual void Validate(IDbContextOptions options)
nameof(InMemoryDbContextOptionsExtensions.UseInMemoryDatabase),
nameof(DbContextOptionsBuilder.UseInternalServiceProvider)));
}

if (inMemoryOptions != null
&& IsNullabilityCheckEnabled != inMemoryOptions.IsNullabilityCheckEnabled)
{
throw new InvalidOperationException(
CoreStrings.SingletonOptionChanged(
nameof(InMemoryDbContextOptionsBuilder.EnableNullChecks),
nameof(DbContextOptionsBuilder.UseInternalServiceProvider)));
}
}

/// <summary>
Expand Down
6 changes: 6 additions & 0 deletions src/EFCore.InMemory/Properties/InMemoryStrings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/EFCore.InMemory/Properties/InMemoryStrings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@
<value>Transactions are not supported by the in-memory store. See http://go.microsoft.com/fwlink/?LinkId=800142</value>
<comment>Warning InMemoryEventId.TransactionIgnoredWarning</comment>
</data>
<data name="NonComposedGroupByNotSupported" xml:space="preserve">
<value>A 'GroupBy' operation which is not composed into aggregate or projection of elements is not supported.</value>
</data>
<data name="NoQueryStrings" xml:space="preserve">
<value>There is no query string because the in-memory provider does not use a string-based query language.</value>
</data>
Expand Down
16 changes: 16 additions & 0 deletions src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -870,6 +870,22 @@ private static Expression GetGroupingKey(Expression key, List<Expression> groupi

return memberInitExpression.Update(updatedNewExpression, memberBindings);

case EntityShaperExpression entityShaperExpression
when entityShaperExpression.ValueBufferExpression is ProjectionBindingExpression projectionBindingExpression:
var entityProjectionExpression = (EntityProjectionExpression)((InMemoryQueryExpression)projectionBindingExpression.QueryExpression)
.GetProjection(projectionBindingExpression);
var readExpressions = new Dictionary<IProperty, MethodCallExpression>();
foreach (var property in GetAllPropertiesInHierarchy(entityProjectionExpression.EntityType))
{
readExpressions[property] = (MethodCallExpression)GetGroupingKey(
entityProjectionExpression.BindProperty(property),
groupingExpressions,
groupingKeyAccessExpression);
}

return entityShaperExpression.Update(
new EntityProjectionExpression(entityProjectionExpression.EntityType, readExpressions));

default:
var index = groupingExpressions.Count;
groupingExpressions.Add(key);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.EntityFrameworkCore.InMemory.Internal;
using System.Linq.Expressions;

namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal;

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public class InMemoryQueryTranslationPreprocessor : QueryTranslationPreprocessor
{
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public InMemoryQueryTranslationPreprocessor(
QueryTranslationPreprocessorDependencies dependencies,
QueryCompilationContext queryCompilationContext)
: base(dependencies, queryCompilationContext)
{
}

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public override Expression Process(Expression query)
{
var result = base.Process(query);

if (result is MethodCallExpression methodCallExpression
&& methodCallExpression.Method.IsGenericMethod
&& (methodCallExpression.Method.GetGenericMethodDefinition() == QueryableMethods.GroupByWithKeySelector
|| methodCallExpression.Method.GetGenericMethodDefinition() == QueryableMethods.GroupByWithKeyElementSelector))
{
throw new InvalidOperationException(
CoreStrings.TranslationFailedWithDetails(methodCallExpression.Print(), InMemoryStrings.NonComposedGroupByNotSupported));
}

return result;
}
}
Loading

0 comments on commit 53db832

Please sign in to comment.