Skip to content

Fix FileConnection Dispose/Open lifecycle (#157, #153)#169

Merged
DaveRMaltby merged 1 commit into
mainfrom
fix/157-153-connection-lifecycle
Mar 22, 2026
Merged

Fix FileConnection Dispose/Open lifecycle (#157, #153)#169
DaveRMaltby merged 1 commit into
mainfrom
fix/157-153-connection-lifecycle

Conversation

@DaveRMaltby
Copy link
Copy Markdown
Contributor

Summary

  • Bug: FileConnection.Dispose() doesn't close the connection properly #157: Override Dispose(bool disposing) instead of using protected new void Dispose() in FileConnection, FileTransaction, and FileDataReader so polymorphic disposal works correctly via base type references (e.g. using (DbConnection conn = ...))
  • Bug: FileConnection.Open() doesn't check if already open #153: FileConnection.Open() now throws InvalidOperationException when called on an already-open connection, per ADO.NET contract
  • Simplified Close() to only transition state; resource cleanup moved to Dispose(bool)
  • Fixed FileDataReader to use Close() override for cleanup to avoid recursion with base DbDataReader.Dispose(bool) calling Close()
  • Updated tests to use Close() + Open() instead of bare re-Open() for data refresh

Test plan

  • All CSV tests pass (128/128)
  • All JSON tests pass (202/202 + 2 skipped)
  • All XML tests pass (154/154)
  • All XLS tests pass (34/34 + 5 skipped)
  • Custom data source tests pass (StreamedDataSource round-trip)

Closes #157, Closes #153

🤖 Generated with Claude Code

…) state check

Fixes #157: FileConnection, FileTransaction, and FileDataReader used
`protected new void Dispose()` which hid the base class Dispose pattern,
preventing polymorphic disposal via base type references (e.g. using
statements with DbConnection type).

Fixes #153: FileConnection.Open() now throws InvalidOperationException
if the connection is already open, per the ADO.NET contract.

Changes:
- FileConnection: override Dispose(bool disposing), add Open() state check,
  simplify Close() to only transition state (Dispose handles resource cleanup)
- FileTransaction: override Dispose(bool disposing) instead of new Dispose()
- FileDataReader: override Dispose(bool disposing), move cleanup to Close()
  override to avoid recursion with base DbDataReader.Dispose(bool)
- Update tests to use Close()+Open() pattern instead of bare re-Open()

Closes #157, Closes #153

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

Summary

Summary
Generated on: 03/22/2026 - 12:50:39
Coverage date: 03/22/2026 - 12:49:17 - 03/22/2026 - 12:50:22
Parser: MultiReport (8x Cobertura)
Assemblies: 10
Classes: 237
Files: 237
Line coverage: 80.9% (5561 of 6871)
Covered lines: 5561
Uncovered lines: 1310
Coverable lines: 6871
Total lines: 18699
Branch coverage: 66.2% (1659 of 2505)
Covered branches: 1659
Total branches: 2505
Method coverage: Feature is only available for sponsors

Coverage

Data.Common - 77.5%
Name Line Branch
Data.Common 77.5% 66.8%
Data.Common.DataSource.DataSourceEventArgs 0% 0%
Data.Common.DataSource.FileSystemDataSource 88.5% 68.1%
Data.Common.DataSource.StreamedDataSource 89.4% 50%
Data.Common.DataSource.TableStreamedDataSource 80% 50%
Data.Common.Extension.FileConnectionExtensions 90.9% 87.5%
Data.Common.Extension.FileConnectionStringTestsExtensions 91.6% 80%
Data.Common.Extension.FloatingPointDataTypeExtensions 66.6% 60%
Data.Common.Extension.IEnumerableExtensions 0% 0%
Data.Common.Extension.ObjectExtensions 50%
Data.Common.Extension.StringExtensions 0% 0%
Data.Common.Extension.VirtualDataTableExtensions 0% 0%
Data.Common.FileException.ColumnNotFoundException 0%
Data.Common.FileException.InvalidConnectionStringException 100%
Data.Common.FileException.InvalidFileException 0%
Data.Common.FileException.QueryNotSupportedException 0%
Data.Common.FileException.QuerySyntaxException 0%
Data.Common.FileException.TableNotFoundException 0%
Data.Common.FileException.ThrowHelper 60% 100%
Data.Common.FileIO.Delete.FileDeleteWriter 100% 85.7%
Data.Common.FileIO.FileWriter 100% 83.3%
Data.Common.FileIO.Read.FileEnumerator 90.6% 71.4%
Data.Common.FileIO.Read.FileReader 91.9% 84%
Data.Common.FileIO.SchemaAltering.FileAddColumnWriter 95.4% 60%
Data.Common.FileIO.SchemaAltering.FileCreateTableWriter 93.9% 71.4%
Data.Common.FileIO.SchemaAltering.FileDropColumnWriter 94.1% 66.6%
Data.Common.FileIO.SchemaAltering.FileDropTableWriter 77.2% 58.3%
Data.Common.FileIO.Write.FileInsertWriter 84.5% 79.7%
Data.Common.FileIO.Write.FileUpdateWriter 93.1% 68.1%
Data.Common.FileStatements.Field 0%
Data.Common.FileStatements.FileAddColumn 100%
Data.Common.FileStatements.FileAdminStatement`1 84.6% 71.4%
Data.Common.FileStatements.FileCreateDatabase`1 88.2% 80%
Data.Common.FileStatements.FileCreateTable 87.5% 50%
Data.Common.FileStatements.FileDelete 90.9% 66.6%
Data.Common.FileStatements.FileDropColumn 100%
Data.Common.FileStatements.FileDropDatabase`1 87.5% 81.2%
Data.Common.FileStatements.FileDropTable 83.3% 50%
Data.Common.FileStatements.FileInsert 83.3% 60%
Data.Common.FileStatements.FileSelect 85.7% 100%
Data.Common.FileStatements.FileStatement 100% 100%
Data.Common.FileStatements.FileStatementCreator 86.4% 75%
Data.Common.FileStatements.FileUpdate 92.3% 66.6%
Data.Common.Parsing.AdminGrammar 100%
Data.Common.Parsing.SqlGrammar 100%
Data.Common.Utils.BufferedResetStream 82.8% 76.7%
Data.Common.Utils.BuiltinFunctionProvider 53.3% 40%
Data.Common.Utils.ConcatStream 70.9% 61.9%
Data.Common.Utils.ConnectionString.AliasAttribute 100%
Data.Common.Utils.ConnectionString.FileConnectionString 82.4% 69.7%
Data.Common.Utils.ConnectionString.FileConnectionStringBuilder 31.8% 19.2%
Data.Common.Utils.DatabaseConnectionProvider 100%
Data.Common.Utils.LoggerServices 83.3% 46.1%
Data.Common.Utils.Result 87.1% 73.9%
Data.Common.Utils.StreamedTableManager 73.1% 61.7%
Data.Common.Utils.StreamHolder 100%
Data.Common.Utils.SubStream 70.2% 62.5%
Data.Common.Utils.SubStreamReader 100% 80%
Data.Common.Utils.TransactionLevelData 95% 78.5%
System.Data.FileClient.CloseConnectionDataReader 27.4% 66.6%
System.Data.FileClient.FileCommand`1 82% 82.2%
System.Data.FileClient.FileCommandBuilder`1 94.4% 100%
System.Data.FileClient.FileConnection`1 75.7% 84.3%
System.Data.FileClient.FileDataAdapter`1 83.1% 72.6%
System.Data.FileClient.FileDataReader 69.8% 40.4%
System.Data.FileClient.FileParameter`1 58% 25%
System.Data.FileClient.FileParameterCollection`1 15.9% 13.6%
System.Data.FileClient.FileTransaction`1 86% 66.6%
Data.Csv - 90.7%
Name Line Branch
Data.Csv 90.7% 87%
CsvTransformStream 88.1% 86.1%
Data.Csv.CsvIO.CsvDataSetWriter 87.1% 88.8%
Data.Csv.CsvIO.Delete.CsvDelete 100%
Data.Csv.CsvIO.Read.CsvReader 92.5% 100%
Data.Csv.CsvIO.SchemaAltering.CsvAddColumn 100%
Data.Csv.CsvIO.SchemaAltering.CsvCreateTable 100%
Data.Csv.CsvIO.SchemaAltering.CsvDropColumn 100%
Data.Csv.CsvIO.SchemaAltering.CsvDropTable 0%
Data.Csv.CsvIO.Write.CsvInsert 92.8% 91.6%
Data.Csv.CsvIO.Write.CsvUpdate 100%
Data.Csv.Utils.CsvSeparatorDetector 95.8% 71.4%
Data.Csv.Utils.CsvVirtualDataTable 95.3% 85.2%
Data.Csv.Utils.TypeGuesser 100% 94.4%
System.Data.CsvClient.CsvClientFactory 80%
System.Data.CsvClient.CsvCommand 85.7% 83.3%
System.Data.CsvClient.CsvCommandBuilder 100%
System.Data.CsvClient.CsvConnection 85.1% 75%
System.Data.CsvClient.CsvDataAdapter 94.1% 83.3%
System.Data.CsvClient.CsvDataReader 100%
System.Data.CsvClient.CsvParameter 60%
System.Data.CsvClient.CsvTransaction 100%
Data.Json - 81.5%
Name Line Branch
Data.Json 81.5% 71.6%
Data.Json.Extension.JsonElementExtensions 0% 0%
Data.Json.Extension.JsonValueKindExtensions 0% 0%
Data.Json.JsonException.InvalidJsonFileException 0%
Data.Json.JsonException.ThrowHelper 0% 0%
Data.Json.JsonIO.Delete.JsonDelete 100%
Data.Json.JsonIO.JsonDataSetWriter 87.5% 66%
Data.Json.JsonIO.Read.JsonReader 100% 75%
Data.Json.JsonIO.SchemaAltering.JsonAddColumn 100%
Data.Json.JsonIO.SchemaAltering.JsonCreateTable 100%
Data.Json.JsonIO.SchemaAltering.JsonDropColumn 100%
Data.Json.JsonIO.SchemaAltering.JsonDropTable 100%
Data.Json.JsonIO.Write.JsonInsert 87.5% 83.3%
Data.Json.JsonIO.Write.JsonUpdate 100%
Data.Json.Utils.BOMHandlingStream 80.6% 82.3%
Data.Json.Utils.JsonConnectionStringBuilder 83.3% 50%
Data.Json.Utils.JsonDatabaseStreamSplitter 92.6% 81.8%
Data.Json.Utils.JsonDatabaseVirtualDataSet 81.2% 90%
Data.Json.Utils.JsonVirtualDataTable 89.6% 81.3%
Data.Json.Utils.StreamJsonReader 78.9% 73.2%
System.Data.JsonClient.JsonClientFactory 80%
System.Data.JsonClient.JsonCommand 90.9% 88.8%
System.Data.JsonClient.JsonCommandBuilder 100%
System.Data.JsonClient.JsonConnection 87.5%
System.Data.JsonClient.JsonDataAdapter 72.7% 50%
System.Data.JsonClient.JsonDataReader 100%
System.Data.JsonClient.JsonParameter 66.6%
System.Data.JsonClient.JsonTransaction 100%
Data.Tests.Common - 88.8%
Name Line Branch
Data.Tests.Common 88.8% 64.4%
AutoGeneratedProgram 0%
Data.Tests.Common.AlterTableTests 100% 50%
Data.Tests.Common.AsyncTests 100% 100%
Data.Tests.Common.BufferedResetStreamTests 0% 0%
Data.Tests.Common.ClientFactoryTests 100%
Data.Tests.Common.CommandBuilderTests 100%
Data.Tests.Common.CommandTests 100% 100%
Data.Tests.Common.ConcurrencyTests 80.7% 30.7%
Data.Tests.Common.ConnectionStringBuilderTests 100%
Data.Tests.Common.ConnectionTests 100% 66.6%
Data.Tests.Common.CreateTableTests 100%
Data.Tests.Common.DeleteTests 100%
Data.Tests.Common.Extensions.FileConnectionExtensions 42.8% 33.3%
Data.Tests.Common.FileAsDatabase.DataAdapterTests 100% 80%
Data.Tests.Common.FileAsDatabase.DataReaderTests 100% 84.2%
Data.Tests.Common.FileSystemDataSourceTests 0%
Data.Tests.Common.InsertTests 99.1% 50%
Data.Tests.Common.POCOs.TestRecord 100%
Data.Tests.Common.SelectTests 0%
Data.Tests.Common.TransactionTests 97.5%
Data.Tests.Common.UpdateTests 100%
Data.Tests.Common.Utils.ConcatStreamTests 0%
Data.Tests.Common.Utils.ConnectionStringsBase 94.7%
Data.Tests.Common.Utils.CustomDataSourceFactory 100% 100%
Data.Tests.Common.Utils.DatabaseFullPaths 100% 50%
Data.Tests.Common.Utils.FileUtils 90% 83.3%
Data.Tests.Common.Utils.FormFileUtils 100%
Data.Tests.Common.Utils.GrammarParser 0% 0%
Data.Tests.Common.Utils.NonSeekableStream 0% 0%
Data.Tests.Common.Utils.UnendingStream 58.6% 76.9%
Data.Xls - 68.4%
Name Line Branch
Data.Xls 68.4% 50%
Data.Xls.DataSource.XlsStreamedDataSource 100% 100%
Data.Xls.Utils.CellExtensions 88.8% 66.6%
Data.Xls.Utils.CsvUtils 100% 100%
Data.Xls.Utils.TypeGuesser 0% 0%
Data.Xls.Utils.WorkbookExtensions 95.6% 75%
Data.Xls.Utils.XlsDatabaseStreamSplitter 100% 83.3%
Data.Xls.Utils.XlsSheetStream 73% 75%
Data.Xls.XlsIO.Read.XlsReader 90.9% 50%
System.Data.XlsClient.XlsClientFactory 50%
System.Data.XlsClient.XlsCommand 15% 5.5%
System.Data.XlsClient.XlsCommandBuilder 66.6%
System.Data.XlsClient.XlsConnection 86.2% 90%
System.Data.XlsClient.XlsDataReader 100%
System.Data.XlsClient.XlsParameter 0%
Data.Xml - 88.2%
Name Line Branch
Data.Xml 88.2% 86.8%
Data.Xml.XmlIO.Delete.XmlDelete 100%
Data.Xml.XmlIO.Read.XmlReader 100% 100%
Data.Xml.XmlIO.SchemaAltering.XmlAddColumn 100%
Data.Xml.XmlIO.SchemaAltering.XmlCreateTable 100%
Data.Xml.XmlIO.SchemaAltering.XmlDropColumn 100%
Data.Xml.XmlIO.SchemaAltering.XmlDropTable 0%
Data.Xml.XmlIO.Write.XmlInsert 75%
Data.Xml.XmlIO.Write.XmlUpdate 100%
Data.Xml.XmlIO.XmlDataSetWriter 84.6% 100%
System.Data.XmlClient.XmlClientFactory 70%
System.Data.XmlClient.XmlCommand 86.3% 88.8%
System.Data.XmlClient.XmlCommandBuilder 100%
System.Data.XmlClient.XmlConnection 100%
System.Data.XmlClient.XmlDataAdapter 72.7% 50%
System.Data.XmlClient.XmlDataReader 100%
System.Data.XmlClient.XmlParameter 60%
System.Data.XmlClient.XmlTransaction 100%
EFCore.Common - 68.5%
Name Line Branch
EFCore.Common 68.5% 53%
EFCore.Common.Design.Internal.FileDesignTimeServices 100%
EFCore.Common.Infrastructure.Internal.FileOptionsExtensionInfo 92.3% 75%
EFCore.Common.Infrastructure.Internal.FileRelationalConnection 100% 100%
EFCore.Common.Query.Internal.FileMathMethodCallTranslator 8.1% 0%
EFCore.Common.Query.Internal.FileMemberTranslator 10.3% 0%
EFCore.Common.Query.Internal.FileMemberTranslatorProvider 100%
EFCore.Common.Query.Internal.FileMethodCallTranslatorProvider 100%
EFCore.Common.Query.Internal.FileStringMethodCallTranslator 60.9% 55.8%
EFCore.Common.Scaffolding.Internal.FileDatabaseModelFactory 100% 83.3%
EFCore.Common.Scaffolding.Internal.FileScaffoldingModelFactory 0%
EFCore.Common.Storage.Internal.FileDatabaseCreator 47.2% 16.6%
EFCore.Common.Storage.Internal.FileTypeMappingSource 96.6% 75%
EFCore.Common.Update.Internal.FileUpdateSqlGeneratorBase 98% 78.5%
EFCore.Common.Utils.OptionsExtensionsHelper 100% 100%
EFCore.Common.Utils.SharedTypeExtensions 100% 50%
EFCore.Csv.Infrastructure.Internal.FileOptionsExtension 85.1% 60%
EFCore.Csv - 68.2%
Name Line Branch
EFCore.Csv 68.2% 46.2%
EFCore.Csv.Design.Internal.CsvDesignTimeServices 100%
EFCore.Csv.Infrastructure.Internal.CsvOptionsExtension 88.8% 100%
EFCore.Csv.Infrastructure.Internal.CsvOptionsExtensionInfo 75%
EFCore.Csv.Metadata.Conventions.CsvConventionSetBuilder 100%
EFCore.Csv.Query.Internal.CsvQuerySqlGenerator 22.2% 20%
EFCore.Csv.Query.Internal.CsvQuerySqlGeneratorFactory 100%
EFCore.Csv.Scaffolding.Internal.CsvCodeGenerator 100% 50%
EFCore.Csv.Scaffolding.Internal.CsvDatabaseModelFactory 100%
EFCore.Csv.Storage.Internal.CsvDatabaseCreator 0% 0%
EFCore.Csv.Storage.Internal.CsvRelationalConnection 100% 100%
EFCore.Csv.Storage.Internal.CsvTypeMappingSource 64.2% 60.5%
EFCore.Csv.Update.Internal.CsvModificationCommandBatchFactory 100%
EFCore.Csv.Update.Internal.CsvUpdateSqlGenerator 100%
Microsoft.EntityFrameworkCore.CsvDbContextOptionsExtensions 43.3% 35.7%
Microsoft.Extensions.DependencyInjection.CsvServiceCollectionExtensions 96.4%
EFCore.Json - 71.8%
Name Line Branch
EFCore.Json 71.8% 57.5%
EFCore.Json.Design.Internal.JsonDesignTimeServices 100%
EFCore.Json.Infrastructure.Internal.JsonOptionsExtension 90% 100%
EFCore.Json.Infrastructure.Internal.JsonOptionsExtensionInfo 75%
EFCore.Json.Metadata.Conventions.JsonConventionSetBuilder 100%
EFCore.Json.Query.Internal.JsonQuerySqlGenerator 0% 0%
EFCore.Json.Query.Internal.JsonQuerySqlGeneratorFactory 60%
EFCore.Json.Scaffolding.Internal.JsonCodeGenerator 100% 50%
EFCore.Json.Scaffolding.Internal.JsonDatabaseModelFactory 100%
EFCore.Json.Storage.Internal.JsonDatabaseCreator 60% 50%
EFCore.Json.Storage.Internal.JsonRelationalConnection 100% 100%
EFCore.Json.Storage.Internal.JsonTypeMappingSource 92.6% 92.1%
EFCore.Json.Update.Internal.JsonModificationCommandBatchFactory 100%
EFCore.Json.Update.Internal.JsonUpdateSqlGenerator 100%
Microsoft.EntityFrameworkCore.JsonDbContextOptionsExtensions 43.3% 35.7%
Microsoft.Extensions.DependencyInjection.JsonServiceCollectionExtensions 96.4%
EFCore.Xml - 73%
Name Line Branch
EFCore.Xml 73% 51.2%
EFCore.Xml.Design.Internal.XmlDesignTimeServices 100%
EFCore.Xml.Infrastructure.Internal.XmlOptionsExtension 90% 100%
EFCore.Xml.Infrastructure.Internal.XmlOptionsExtensionInfo 75%
EFCore.Xml.Metadata.Conventions.XmlConventionSetBuilder 100%
EFCore.Xml.Query.Internal.XmlQuerySqlGenerator 44.4% 35%
EFCore.Xml.Query.Internal.XmlQuerySqlGeneratorFactory 100%
EFCore.Xml.Scaffolding.Internal.XmlCodeGenerator 100% 50%
EFCore.Xml.Scaffolding.Internal.XmlDatabaseModelFactory 100%
EFCore.Xml.Storage.Internal.XmlDatabaseCreator 60% 50%
EFCore.Xml.Storage.Internal.XmlRelationalConnection 100% 100%
EFCore.Xml.Storage.Internal.XmlTypeMappingSource 64.2% 60.5%
EFCore.Xml.Update.Internal.XmlModificationCommandBatchFactory 100%
EFCore.Xml.Update.Internal.XmlUpdateSqlGenerator 100%
Microsoft.EntityFrameworkCore.XmlDbContextOptionsExtensions 43.3% 35.7%
Microsoft.Extensions.DependencyInjection.XmlServiceCollectionExtensions 96.4%

@DaveRMaltby DaveRMaltby merged commit be71db9 into main Mar 22, 2026
1 check passed
@DaveRMaltby DaveRMaltby deleted the fix/157-153-connection-lifecycle branch March 22, 2026 12:58
@DaveRMaltby DaveRMaltby restored the fix/157-153-connection-lifecycle branch March 22, 2026 14:53
@DaveRMaltby DaveRMaltby deleted the fix/157-153-connection-lifecycle branch April 5, 2026 14:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: FileConnection.Dispose() doesn't close the connection properly Bug: FileConnection.Open() doesn't check if already open

1 participant