Analysis of commit 756cdee
Assignee: @copilot
Summary
OdbcDataConnection and OleDataConnection in src/Adapter/MSTestAdapter.PlatformServices/Data/ both extend TestDataConnectionSql and implement nearly the same database schema retrieval, identifier quoting, and connection-string fix-up logic. The two files are structurally very similar (~100 lines each), sharing identical patterns for GetTablesForSchema, QuoteIdentifier, UnquoteIdentifier, and connection-string path fixing — with differences only in the underlying ADO.NET provider types (Odbc* vs OleDb*).
Duplication Details
Pattern: Parallel ADO.NET Provider Implementations with Shared Logic
- Severity: Medium
- Occurrences: 2 files (~198 lines combined, ~60% structurally duplicated)
- Locations:
src/Adapter/MSTestAdapter.PlatformServices/Data/OdbcDataConnection.cs (lines 1–105)
src/Adapter/MSTestAdapter.PlatformServices/Data/OleDataConnection.cs (lines 1–93)
The files share:
| Section |
OdbcDataConnection |
OleDataConnection |
| Constructor (lines 19–27) |
Connection.Driver → IsMSSql(...) |
Connection.Provider → IsMSSql(...) |
CommandBuilder property |
OdbcCommandBuilder cast |
OleDbCommandBuilder cast |
Connection property |
OdbcConnection cast |
OleDbConnection cast |
QuoteIdentifier (lines 64–66) |
CommandBuilder.QuoteIdentifier(id, Connection) |
identical |
UnquoteIdentifier (lines 70–72) |
CommandBuilder.UnquoteIdentifier(id, Connection) |
identical |
FixupConnectionString pattern |
DSN/Excel path fix |
DataSource path fix |
GetTablesForSchema structure |
SchemaMetaData lookup |
SchemaMetaData lookup |
- Code Sample (identical quoting methods):
// OdbcDataConnection.cs (lines 63–73) — IDENTICAL in both files
protected override string QuoteIdentifier(string identifier)
{
return CommandBuilder.QuoteIdentifier(identifier, Connection); // Must pass connection.
}
protected override string UnquoteIdentifier(string identifier)
{
return CommandBuilder.UnquoteIdentifier(identifier, Connection); // Must pass connection.
}
// OleDataConnection.cs (lines 57–65) — structurally identical
protected override string QuoteIdentifier(string identifier)
{
return CommandBuilder.QuoteIdentifier(identifier, Connection);
}
protected override string UnquoteIdentifier(string identifier)
{
return CommandBuilder.UnquoteIdentifier(identifier, Connection);
}
Impact Analysis
- Maintainability: Any change to schema retrieval or quoting logic must be applied in parallel to both files. The
GetTablesForSchema methods diverge in schema column names (TABLE_SCHEM vs TABLE_SCHEMA) and valid table types, making them harder to spot as candidates for sharing.
- Bug Risk: Medium — a fix to connection-string path normalization in one file may not be applied to the other.
- Code Bloat: ~60 lines of duplicated code between the two files.
Refactoring Recommendations
-
Move identical QuoteIdentifier/UnquoteIdentifier to the TestDataConnectionSql base class
- Both implementations call
CommandBuilder.QuoteIdentifier(identifier, Connection) identically. These two methods can be moved up to the base class and removed from both OdbcDataConnection and OleDataConnection.
- The base class
TestDataConnectionSql already owns CommandBuilder and Connection, so the move is straightforward.
- File:
src/Adapter/MSTestAdapter.PlatformServices/Data/TestDataConnectionSql.cs
- Estimated effort: Low (2–4 hours)
-
Extract shared IsMSSql detection
- Both constructors call
IsMSSql(Connection.Driver) / IsMSSql(Connection.Provider) to set _isMSSql. The IsMSSql method is defined in TestDataConnectionSql. A virtual/abstract GetProviderName(DbConnection conn) hook on the base class could unify the constructor logic.
-
Consider a template-method pattern for FixupConnectionString
- The path fix-up logic follows the same pattern (find file path → normalize → update connection string) but uses provider-specific
ConnectionStringBuilder types. A protected virtual UpdateFilePath(string fixedPath) on the base class could handle the update step.
Implementation Checklist
Analysis Metadata
- Analyzed Files: 2 (OdbcDataConnection.cs, OleDataConnection.cs) + base class (TestDataConnectionSql.cs)
- Detection Method: Semantic code analysis + structural diff
- Commit: 756cdee
- Analysis Date: 2026-06-06
Generated by Duplicate Code Detector · sonnet46 3.8M · ◷
Add this agentic workflows to your repo
To install this agentic workflow, run
gh aw add githubnext/agentics/workflows/duplicate-code-detector.md@main
Analysis of commit 756cdee
Assignee:
@copilotSummary
OdbcDataConnectionandOleDataConnectioninsrc/Adapter/MSTestAdapter.PlatformServices/Data/both extendTestDataConnectionSqland implement nearly the same database schema retrieval, identifier quoting, and connection-string fix-up logic. The two files are structurally very similar (~100 lines each), sharing identical patterns forGetTablesForSchema,QuoteIdentifier,UnquoteIdentifier, and connection-string path fixing — with differences only in the underlying ADO.NET provider types (Odbc*vsOleDb*).Duplication Details
Pattern: Parallel ADO.NET Provider Implementations with Shared Logic
src/Adapter/MSTestAdapter.PlatformServices/Data/OdbcDataConnection.cs(lines 1–105)src/Adapter/MSTestAdapter.PlatformServices/Data/OleDataConnection.cs(lines 1–93)The files share:
Connection.Driver→IsMSSql(...)Connection.Provider→IsMSSql(...)CommandBuilderpropertyOdbcCommandBuildercastOleDbCommandBuildercastConnectionpropertyOdbcConnectioncastOleDbConnectioncastQuoteIdentifier(lines 64–66)CommandBuilder.QuoteIdentifier(id, Connection)UnquoteIdentifier(lines 70–72)CommandBuilder.UnquoteIdentifier(id, Connection)FixupConnectionStringpatternGetTablesForSchemastructureImpact Analysis
GetTablesForSchemamethods diverge in schema column names (TABLE_SCHEMvsTABLE_SCHEMA) and valid table types, making them harder to spot as candidates for sharing.Refactoring Recommendations
Move identical
QuoteIdentifier/UnquoteIdentifierto theTestDataConnectionSqlbase classCommandBuilder.QuoteIdentifier(identifier, Connection)identically. These two methods can be moved up to the base class and removed from bothOdbcDataConnectionandOleDataConnection.TestDataConnectionSqlalready ownsCommandBuilderandConnection, so the move is straightforward.src/Adapter/MSTestAdapter.PlatformServices/Data/TestDataConnectionSql.csExtract shared
IsMSSqldetectionIsMSSql(Connection.Driver)/IsMSSql(Connection.Provider)to set_isMSSql. TheIsMSSqlmethod is defined inTestDataConnectionSql. A virtual/abstractGetProviderName(DbConnection conn)hook on the base class could unify the constructor logic.Consider a template-method pattern for
FixupConnectionStringConnectionStringBuildertypes. A protected virtualUpdateFilePath(string fixedPath)on the base class could handle the update step.Implementation Checklist
QuoteIdentifier/UnquoteIdentifiertoTestDataConnectionSqlbase class (lowest risk, highest impact)GetProviderName(DbConnection)to unify the_isMSSqlassignment patternFixupConnectionStringAnalysis Metadata
Add this agentic workflows to your repo
To install this agentic workflow, run