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

Avoid using a disposed connection in HistoryRepository #405

Merged
merged 1 commit into from Nov 27, 2017
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion EntityFramework.sln.DotSettings
Expand Up @@ -68,4 +68,5 @@
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002EJavaScript_002ECodeStyle_002ESettingsUpgrade_002EJsCodeFormatterSettingsUpgrader/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002EJavaScript_002ECodeStyle_002ESettingsUpgrade_002EJsParsFormattingSettingsUpgrader/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002EJavaScript_002ECodeStyle_002ESettingsUpgrade_002EJsWrapperSettingsUpgrader/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002EJavaScript_002ECodeStyle_002ESettingsUpgrade_002EJsWrapperSettingsUpgrader/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002EXml_002ECodeStyle_002EFormatSettingsUpgrade_002EXmlMoveToCommonFormatterSettingsUpgrade/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
32 changes: 18 additions & 14 deletions src/EntityFramework/Internal/RepositoryBase.cs
Expand Up @@ -9,7 +9,7 @@ namespace System.Data.Entity.Internal

internal abstract class RepositoryBase
{
private readonly DbConnection _existingConnection;
private readonly InternalContext _usersContext;
private readonly string _connectionString;
private readonly DbProviderFactory _providerFactory;

Expand All @@ -19,27 +19,30 @@ protected RepositoryBase(InternalContext usersContext, string connectionString,
DebugCheck.NotEmpty(connectionString);
DebugCheck.NotNull(providerFactory);

var existingConnection = usersContext.Connection;
if (existingConnection != null)
{
_existingConnection = existingConnection;
}

_usersContext = usersContext;
_connectionString = connectionString;
_providerFactory = providerFactory;
}

protected DbConnection CreateConnection()
{
if (_existingConnection != null
&& _existingConnection.State == ConnectionState.Open)
DbConnection connection;
if (!_usersContext.IsDisposed
&& (connection = _usersContext.Connection) != null)
{
if (connection.State == ConnectionState.Open)
{
return connection;
}

connection = DbProviderServices.GetProviderServices(connection)
.CloneDbConnection(connection, _providerFactory);
}
else
{
return _existingConnection;
connection = _providerFactory.CreateConnection();
}

var connection = _existingConnection == null
? _providerFactory.CreateConnection()
: DbProviderServices.GetProviderServices(_existingConnection).CloneDbConnection(_existingConnection, _providerFactory);
DbInterception.Dispatch.Connection.SetConnectionString(connection,
new DbConnectionPropertyInterceptionContext<string>().WithValue(_connectionString));

Expand All @@ -48,7 +51,8 @@ protected DbConnection CreateConnection()

protected void DisposeConnection(DbConnection connection)
{
if (connection != null && _existingConnection == null)
if (connection != null
&& (_usersContext.IsDisposed || connection != _usersContext.Connection))
{
DbInterception.Dispatch.Connection.Dispose(connection, new DbInterceptionContext());
}
Expand Down
1 change: 1 addition & 0 deletions src/EntityFramework/Migrations/DbMigrator.cs
Expand Up @@ -210,6 +210,7 @@ var modelBuilder
if (usersContext == null)
{
_usersContext = null;
_connection = null;
context.Dispose();
}
}
Expand Down
Expand Up @@ -6,7 +6,7 @@ namespace System.Data.Entity.WrappingProvider

public class WrappingConnection<TBase> : DbConnection, IDisposable where TBase : DbProviderFactory
{
private readonly DbConnection _baseConnection;
private DbConnection _baseConnection;

public WrappingConnection(DbConnection baseConnection)
{
Expand Down Expand Up @@ -89,6 +89,7 @@ public DbConnection BaseConnection
public new void Dispose()
{
_baseConnection.Dispose();
_baseConnection = null;
}
}
}
Expand Up @@ -9,12 +9,14 @@ namespace System.Data.Entity.WrappingProvider
using System.Data.Entity.Functionals.Utilities;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.Infrastructure.DependencyResolution;
using System.Data.Entity.Migrations;
using System.Data.Entity.Migrations.Sql;
using System.Data.Entity.SqlServer;
using System.Data.Entity.TestHelpers;
using System.Data.SqlClient;
using System.Linq;
using System.Reflection;
using FunctionalTests.SimpleMigrationsModel;
using Xunit;

public class WrappingProviderTests : FunctionalTestBase, IDisposable
Expand Down Expand Up @@ -200,6 +202,38 @@ public void Simple_query_and_update_works_with_wrapping_provider_setup_at_EF_lev
Assert.Contains("Generate", methods);
}

[Fact]
[UseDefaultExecutionStrategy]
public void Migrations_work_with_wrapping_provider_setup_by_replacing_ADO_NET_provider()
{
RegisterAdoNetProvider(typeof(WrappingAdoNetProvider<SqlClientFactory>));
MutableResolver.AddResolver<DbProviderServices>(k => WrappingEfProvider<SqlClientFactory, SqlProviderServices>.Instance);
MutableResolver.AddResolver<Func<MigrationSqlGenerator>>(WrappingEfProvider<SqlClientFactory, SqlProviderServices>.Instance);

var log = WrappingAdoNetProvider<SqlClientFactory>.Instance.Log;
log.Clear();

using (var context = new MigrationsBlogContext())
{
context.Database.Delete();
}

using (var context = new MigrationsBlogContext())
{
Assert.False(context.Database.Exists());
}

var migrator = new DbMigrator(new MigrateInitializerConfiguration());
var appliedMigrations = migrator.GetDatabaseMigrations();
Assert.Equal(2, appliedMigrations.Count());

// Sanity check that the wrapping provider really did get used
var methods = log.Select(i => i.Method).ToList();
Assert.Contains("ExecuteReader", methods);
Assert.Contains("Open", methods);
Assert.Contains("Close", methods);
}

[Fact] // CodePlex 2320
public void Model_is_available_in_DatabaseExists()
{
Expand Down Expand Up @@ -254,6 +288,22 @@ static EfLevelBlogContext()
}
}

public class MigrationsBlogContext : BlogContext
{
static MigrationsBlogContext()
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<MigrationsBlogContext, MigrationsBlogConfiguration>());
}
}

public class MigrationsBlogConfiguration : DbMigrationsConfiguration<MigrationsBlogContext>
{
public MigrationsBlogConfiguration()
{
MigrationsNamespace = "FunctionalTests.MigrationsBlogContext";
}
}

public abstract class BlogContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
Expand Down