3 minute read

LINQPad provides a highly effective environment for running C# and SQL side-by-side, allowing us to write, execute, and visualize results in a single place without constantly switching between an IDE and separate database tools. This tight feedback loop makes LINQPad ideal for exploratory querying, debugging, rapid prototyping, and validating data logic, especially when working directly with live databases.

With built-in support for multiple database providers, LINQPad is particularly well-suited for workflows involving both SQL Server and Oracle. We can connect to multiple databases simultaneously, browse schemas, and execute provider-specific SQL while keeping our C# logic consistent. LINQPad can be downloaded from the official site: https://www.linqpad.net/Download.aspx.


Step 1: Setting Up Connections

Before working with database connections in LINQPad, we ensure the correct provider libraries are available.

SQL Server

To use SqlConnection and SqlCommand, we add a reference to System.Data.SqlClient. This reference can be added by pressing F4 in LINQPad to open Query Properties, then adding the required assembly.

Oracle

For Oracle connectivity, we add a reference to Oracle.ManagedDataAccess. This reference can also be added via F4, allowing us to work with Oracle databases using the managed provider without installing a full Oracle client.

After adding the required references, we configure the appropriate SQL Server or Oracle connection in LINQPad and use the active connection’s connection string directly within our C# code.


Step 2: Writing C# with Embedded SQL (Shared Pattern)

Rather than relying on different examples for each database, we can follow one consistent C# pattern for executing SQL against both SQL Server and Oracle. The only changes required are:

  • the active LINQPad connection
  • the provider-specific SQL syntax (if needed)

To keep our scripts clean and maintainable, we can separate model definitions from query logic. The #load "Model/AccessRecord" directive imports an external C# file containing the AccessRecord model into the current LINQPad script. This approach allows us to reuse strongly typed models across multiple queries, reduce duplication, and keep the main script focused on execution rather than structure.

Below is a shared example that demonstrates how we read records from a database table and materialize them into a strongly typed model. This approach works equally well for SQL Server and Oracle when the appropriate provider and SQL syntax are used.

#load "Model/AccessRecord"

// Main method executed by LINQPad
void Main()
{
    // Retrieve the connection string from the active LINQPad connection
    string connectionString = this.Connection.ConnectionString;

    using (var connection = new SqlConnection(connectionString))
    {
        connection.Open();

        string sql = @"SELECT TOP (100) 
                            [t0].[handle_id] AS [Handle_id], 
                            [t0].[user_id] AS [User_id], 
                            [t0].[op] AS [Op], 
                            [t0].[opDate] AS [OpDate], 
                            [t0].[commentText] AS [CommentText], 
                            [t0].[changeData] AS [ChangeData]
                       FROM [accessTable] AS [t0]";

        using (var command = new SqlCommand(sql, connection))
        using (var reader = command.ExecuteReader())
        {
            var results = new List<AccessRecord>();

            while (reader.Read())
            {
                var record = new AccessRecord
                {
                    Handle_id   = reader["Handle_id"]?.ToString(),
                    User_id     = reader["User_id"]?.ToString(),
                    Op          = reader["Op"]?.ToString(),
                    OpDate      = reader.IsDBNull(reader.GetOrdinal("OpDate"))
                                    ? (DateTime?)null
                                    : reader.GetDateTime(reader.GetOrdinal("OpDate")),
                    CommentText = reader["CommentText"]?.ToString(),
                    ChangeData  = reader["ChangeData"]?.ToString()
                };

                results.Add(record);
            }

            // Visualize results directly in LINQPad
            results.Dump("Access Table Records");

            // Output record count
            Console.WriteLine($"Total records retrieved: {results.Count}");
        }
    }
}

For Oracle, we apply the same structure while adjusting:

  • the connection provider
  • SQL syntax (for example, replacing TOP (100) with an Oracle-compatible equivalent)

This keeps our logic consistent and easy to reason about across databases.


Step 3: Cross-Database Workflows

Because LINQPad allows multiple connections in the same script, we can read data from one database and write it to another without changing tools or execution context. This makes LINQPad especially effective for:

  • data validation
  • migration dry-runs
  • schema comparisons
  • transformation testing

By keeping the C# logic unified, we reduce duplication and lower the risk of inconsistencies.


Step 4: Leveraging LINQPad Features for Efficiency

LINQPad offers several features that significantly improve productivity:

  • Auto-completion and syntax highlighting help us write correct SQL and C# faster.
  • The .Dump() method gives instant visibility into query results and object graphs.
  • Reusable query snippets allow us to standardize common database access patterns across scripts.

These features are particularly valuable when working with multiple database providers.


Step 5: Practical Tips

  • We keep SQL focused on data retrieval and use C# for transformation and validation.
  • We name connections clearly (for example, SQLServer_Main, Oracle_HR) to avoid mistakes.
  • We always test with small data sets before running inserts or updates at scale.
  • We prefer strongly typed models to catch issues early and improve maintainability.

By running C# and SQL side-by-side in LINQPad, we streamline database workflows and work more efficiently within a single, unified environment. This approach reduces friction, accelerates iteration, and is especially effective in cross-database ecosystems involving SQL Server and Oracle.

Leave a comment