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

Merge ExistingConnectionTest with ConnectionSpecificationTest #22412

Merged
1 commit merged into from
Sep 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 21 additions & 24 deletions src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -334,24 +334,19 @@ protected virtual void ValidateSharedTableCompatibility(
continue;
}

if (mappedType.FindPrimaryKey() != null
&& mappedType.FindForeignKeys(mappedType.FindPrimaryKey().Properties)
.Any(
fk => fk.PrincipalKey.IsPrimaryKey()
&& unvalidatedTypes.Contains(fk.PrincipalEntityType)))
var primaryKey = mappedType.FindPrimaryKey();
if (primaryKey != null
&& (mappedType.FindForeignKeys(primaryKey.Properties)
.FirstOrDefault(fk => fk.PrincipalKey.IsPrimaryKey()
&& unvalidatedTypes.Contains(fk.PrincipalEntityType)) is IForeignKey linkingFK))
{
if (mappedType.BaseType != null)
{
var principalType = mappedType.FindForeignKeys(mappedType.FindPrimaryKey().Properties)
.First(
fk => fk.PrincipalKey.IsPrimaryKey()
&& unvalidatedTypes.Contains(fk.PrincipalEntityType))
.PrincipalEntityType;
throw new InvalidOperationException(
RelationalStrings.IncompatibleTableDerivedRelationship(
storeObject.DisplayName(),
mappedType.DisplayName(),
principalType.DisplayName()));
linkingFK.PrincipalEntityType.DisplayName()));
}

continue;
Expand Down Expand Up @@ -388,18 +383,21 @@ protected virtual void ValidateSharedTableCompatibility(

foreach (var nextEntityType in directlyConnectedTypes)
{
var otherKey = nextEntityType.FindPrimaryKey();
if (key?.GetName(storeObject) != otherKey?.GetName(storeObject))
if (key != null)
{
throw new InvalidOperationException(
RelationalStrings.IncompatibleTableKeyNameMismatch(
storeObject.DisplayName(),
entityType.DisplayName(),
nextEntityType.DisplayName(),
key?.GetName(storeObject),
key?.Properties.Format(),
otherKey?.GetName(storeObject),
otherKey?.Properties.Format()));
var otherKey = nextEntityType.FindPrimaryKey();
if (key.GetName(storeObject) != otherKey.GetName(storeObject))
{
throw new InvalidOperationException(
RelationalStrings.IncompatibleTableKeyNameMismatch(
storeObject.DisplayName(),
entityType.DisplayName(),
nextEntityType.DisplayName(),
key.GetName(storeObject),
key.Properties.Format(),
otherKey.GetName(storeObject),
otherKey.Properties.Format()));
}
}

var nextComment = nextEntityType.GetComment();
Expand Down Expand Up @@ -599,8 +597,7 @@ protected virtual void ValidateSharedViewCompatibility(

private static bool IsIdentifyingPrincipal(IEntityType dependentEntityType, IEntityType principalEntityType)
=> dependentEntityType.FindForeignKeys(dependentEntityType.FindPrimaryKey().Properties)
.Any(
fk => fk.PrincipalKey.IsPrimaryKey()
.Any(fk => fk.PrincipalKey.IsPrimaryKey()
&& fk.PrincipalEntityType == principalEntityType);

/// <summary>
Expand Down
14 changes: 6 additions & 8 deletions src/EFCore/ChangeTrackingStrategy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,12 @@ public enum ChangeTrackingStrategy
/// <para>
/// To use this strategy, the entity class must implement <see cref="INotifyPropertyChanged" /> and
/// <see cref="INotifyPropertyChanging" />.
/// Original values are recorded when the entity raises the <see cref="INotifyPropertyChanging.PropertyChanging" /> event. Properties
/// are
/// marked as modified when the entity raises the <see cref="INotifyPropertyChanged.PropertyChanged" /> event.
/// Original values are recorded when the entity raises the <see cref="INotifyPropertyChanging.PropertyChanging" /> event.
/// Properties are marked as modified when the entity raises the <see cref="INotifyPropertyChanged.PropertyChanged" /> event.
/// </para>
/// <para>
/// Original values are only recorded when they are required to save changes to the entity. For example, properties that are configured
/// as
/// concurrency tokens.
/// Original values are only recorded when they are required to save changes to the entity. For example, properties that are
/// configured as concurrency tokens.
/// </para>
/// </summary>
ChangingAndChangedNotifications,
Expand All @@ -46,8 +44,8 @@ public enum ChangeTrackingStrategy
/// <para>
/// To use this strategy, the entity class must implement <see cref="INotifyPropertyChanged" /> and
/// <see cref="INotifyPropertyChanging" />.
/// Original values are recorded when the entity raises the <see cref="INotifyPropertyChanging.PropertyChanging" />. Properties are
/// marked as modified when the entity raises the <see cref="INotifyPropertyChanged.PropertyChanged" /> event.
/// Original values are recorded when the entity raises the <see cref="INotifyPropertyChanging.PropertyChanging" />.
/// Properties are marked as modified when the entity raises the <see cref="INotifyPropertyChanged.PropertyChanged" /> event.
/// </para>
/// <para>
/// Original values are recorded for all properties, regardless of whether they are required to save changes to the entity.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,21 +38,21 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions
/// </para>
/// </summary>
public class ForeignKeyPropertyDiscoveryConvention :
IForeignKeyAddedConvention,
INavigationAddedConvention,
IPropertyAddedConvention,
IEntityTypeMemberIgnoredConvention,
IPropertyNullabilityChangedConvention,
IPropertyFieldChangedConvention,
IEntityTypePrimaryKeyChangedConvention,
IForeignKeyAddedConvention,
IForeignKeyPropertiesChangedConvention,
IForeignKeyPrincipalEndChangedConvention,
IForeignKeyUniquenessChangedConvention,
IForeignKeyRequirednessChangedConvention,
ISkipNavigationForeignKeyChangedConvention,
ISkipNavigationInverseChangedConvention,
IKeyAddedConvention,
IKeyRemovedConvention,
IEntityTypePrimaryKeyChangedConvention,
INavigationAddedConvention,
ISkipNavigationForeignKeyChangedConvention,
ISkipNavigationInverseChangedConvention,
IPropertyAddedConvention,
IPropertyNullabilityChangedConvention,
IPropertyFieldChangedConvention,
IModelFinalizingConvention
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ public class RelationshipDiscoveryConvention :
IEntityTypeAddedConvention,
IEntityTypeIgnoredConvention,
IEntityTypeBaseTypeChangedConvention,
INavigationRemovedConvention,
IEntityTypeMemberIgnoredConvention,
INavigationRemovedConvention,
INavigationAddedConvention,
IForeignKeyOwnershipChangedConvention
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.TestUtilities;
Expand Down Expand Up @@ -450,5 +452,90 @@ private class Customer
public string Fax { get; set; }
// ReSharper restore UnusedMember.Local
}

[ConditionalTheory]
[InlineData(true)]
[InlineData(false)]
public async Task Can_use_an_existing_closed_connection_test(bool openConnection)
{
var serviceProvider = new ServiceCollection()
.AddEntityFrameworkSqlServer()
.BuildServiceProvider();

using var store = SqlServerTestStore.GetNorthwindStore();
store.CloseConnection();

var openCount = 0;
var closeCount = 0;
var disposeCount = 0;

using var connection = new SqlConnection(store.ConnectionString);
if (openConnection)
{
await connection.OpenAsync();
}

connection.StateChange += (_, a) =>
{
switch (a.CurrentState)
{
case ConnectionState.Open:
openCount++;
break;
case ConnectionState.Closed:
closeCount++;
break;
}
};
connection.Disposed += (_, __) => disposeCount++;

using (var context = new NorthwindContext(serviceProvider, connection))
{
Assert.Equal(91, await context.Customers.CountAsync());
}

if (openConnection)
{
Assert.Equal(ConnectionState.Open, connection.State);
Assert.Equal(0, openCount);
Assert.Equal(0, closeCount);
}
else
{
Assert.Equal(ConnectionState.Closed, connection.State);
Assert.Equal(1, openCount);
Assert.Equal(1, closeCount);
}

Assert.Equal(0, disposeCount);
}

private class NorthwindContext : DbContext
{
private readonly IServiceProvider _serviceProvider;
private readonly SqlConnection _connection;

public NorthwindContext(IServiceProvider serviceProvider, SqlConnection connection)
{
_serviceProvider = serviceProvider;
_connection = connection;
}

// ReSharper disable once UnusedAutoPropertyAccessor.Local
public DbSet<Customer> Customers { get; set; }

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseSqlServer(_connection, b => b.ApplyConfiguration())
.UseInternalServiceProvider(_serviceProvider);

protected override void OnModelCreating(ModelBuilder modelBuilder)
=> modelBuilder.Entity<Customer>(
b =>
{
b.HasKey(c => c.CustomerID);
b.ToTable("Customers");
});
}
}
}
124 changes: 0 additions & 124 deletions test/EFCore.SqlServer.FunctionalTests/ExistingConnectionTest.cs

This file was deleted.