Skip to content

[duplicate-code] Duplicate Code: Shared Logic Between OdbcDataConnection and OleDataConnection #8876

@Evangelink

Description

@Evangelink

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.DriverIsMSSql(...) Connection.ProviderIsMSSql(...)
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

  1. 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)
  2. 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.
  3. 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

  • Review duplication findings
  • Move QuoteIdentifier/UnquoteIdentifier to TestDataConnectionSql base class (lowest risk, highest impact)
  • Add a virtual GetProviderName(DbConnection) to unify the _isMSSql assignment pattern
  • Evaluate feasibility of a template-method for FixupConnectionString
  • Run MSTestAdapter.PlatformServices unit/integration tests to confirm no regressions

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
  • expires on Jun 8, 2026, 5:37 AM UTC

Metadata

Metadata

Labels

type/automationCreated or maintained by an agentic workflow.type/tech-debtCode health, refactoring, simplification.

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions