This guide provides a detailed, step-by-step walkthrough for creating an ASP.NET Core Blazor Web App that performs full CRUD (Create, Read, Update, Delete) operations on an Oracle database. We will build the application progressively, with each section representing a complete, functional stage of development.

Why dotConnect for Oracle?

ORM support provided

Advanced ORM support

Fully supports EF Core, Dapper, NHibernate, LinqConnect, and other technologies for efficient data management.

Full ADO.NET compliance

Full ADO.NET compliance

Conforms to the latest ADO.NET standards and innovations for seamless integration with .NET applications.

Support for Oracle-specific data types

Oracle-specific data types

Offers many Oracle-specific features and fully supports all unique data types for accurate and complete data representation.

Secure connection ensured

Secure connection options

Provides robust security with support for SSL/SSH connections, connecting via proxy servers, embedded servers, and HTTP tunneling.

Integration with popular IDEs

IDE integration

Features native integration with Visual Studio and complete design-time support for accelerated development.

Priority support provided

Priority support & frequent updates

Includes priority support, detailed documentation, and regular updates for continuous improvement.

Download and activate dotConnect for Oracle

You can start using dotConnect for Oracle immediately with a 30-day free trial. Choose one of the following installation options:

30-day free trial version

dotnet add package Devart.Data.Oracle
Install-Package Devart.Data.Oracle

You can install the driver by using the Windows installer.

After you receive the license key, add it to your connection strings to connect to the data source.

Start using dotConnect for Oracle in your project today with a free trial

Select Oracle database objects

Using the built-in Data Explorer, first, configure the connection to Oracle and then select the objects you want to use in your project.

1. In Visual Studio, click Tools on the menu bar and select Connect to Database from the drop-down list.

Connect to Database

2. In the Add Connection window, choose the Oracle data source, fill in the connection details for your Oracle database, and click OK to proceed.

Add connection details

3. In Server Explorer, select the tables and fields you want to use. In our tutorial, we will use the EMPLOYEES table.

Selected Employee table

Connection setup

Open the appsettings.json file and add your Oracle connection string:

{
  "ConnectionStrings": {
    "DefaultConnection": "Direct=True;Host=127.0.0.1;Service Name=OracleDb;User ID=TestUser;Password=TestPassword;License key=**********"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*"
}

Connect and retrieve Oracle data

In this foundational step, our goal is to establish a connection to the Oracle database and display data in a read-only table. This ensures our database connection and data service are correctly configured and provides the foundation for the other CRUD operations.

The data model (Employee.cs)

In your project, create a new folder named Data. Inside it, create a class file named Employee.cs. This class maps directly to the columns of the EMPLOYEES table.

// Data/Employee.cs
namespace OracleBlazor.Data;

public class Employee
{
    public int EmployeeId { get; set; }
    public string FirstName { get; set; } = string.Empty;
    public string LastName { get; set; } = string.Empty;
    public string Email { get; set; } = string.Empty;
    public DateTime HireDate { get; set; }
    public decimal Salary { get; set; }
}

The data service (EmployeeService.cs)

In the Data folder, create a new class EmployeeService.cs. This service encapsulates all database interaction logic. The connection string is read through IConfiguration, which is provided via dependency injection.

// Data/EmployeeService.cs
using Devart.Data.Oracle;

namespace OracleBlazor.Data;

public class EmployeeService
{
    private readonly string _connectionString;

    public EmployeeService(IConfiguration configuration)
    {
        _connectionString = configuration.GetConnectionString("DefaultConnection")!;
    }

    public async Task<List<Employee>> GetAllEmployeesAsync()
    {
        var employees = new List<Employee>();
        using var connection = new OracleConnection(_connectionString);
        await connection.OpenAsync();
        using var command = new OracleCommand(
            "SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME, EMAIL, HIRE_DATE, SALARY FROM EMPLOYEES ORDER BY EMPLOYEE_ID",
            connection);
        using var reader = await command.ExecuteReaderAsync();
        while (await reader.ReadAsync())
        {
            employees.Add(new Employee
            {
                EmployeeId = reader.GetInt32(reader.GetOrdinal("EMPLOYEE_ID")),
                FirstName = reader.GetString(reader.GetOrdinal("FIRST_NAME")),
                LastName = reader.GetString(reader.GetOrdinal("LAST_NAME")),
                Email = reader.GetString(reader.GetOrdinal("EMAIL")),
                HireDate = reader.GetDateTime(reader.GetOrdinal("HIRE_DATE")),
                Salary = reader.GetDecimal(reader.GetOrdinal("SALARY"))
            });
        }
        return employees;
    }
}

Registering the service

In Program.cs, register the EmployeeService as a scoped service so it can be injected into our Blazor components.

// Program.cs
using OracleBlazor.Components;
using OracleBlazor.Data;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents();

// Register the EmployeeService
builder.Services.AddScoped<EmployeeService>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error", createScopeForErrors: true);
    app.UseHsts();
}
app.UseStatusCodePagesWithReExecute("/not-found", createScopeForStatusCodePages: true);
app.UseHttpsRedirection();

app.UseAntiforgery();

app.MapStaticAssets();
app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode();

app.Run();

The Employees page (Employees.razor)

In the Components/Pages folder, create a new Razor Component named Employees.razor. This page fetches and displays the data in a table.

@page "/employees"
@rendermode InteractiveServer
@using OracleBlazor.Data
@inject EmployeeService EmployeeSvc

<PageTitle>Employees</PageTitle>

<h1>Employees</h1>

@if (employees == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>ID</th>
                <th>First Name</th>
                <th>Last Name</th>
                <th>Email</th>
                <th>Hire Date</th>
                <th>Salary</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var emp in employees)
            {
                <tr>
                    <td>@emp.EmployeeId</td>
                    <td>@emp.FirstName</td>
                    <td>@emp.LastName</td>
                    <td>@emp.Email</td>
                    <td>@emp.HireDate.ToString("yyyy-MM-dd")</td>
                    <td>@emp.Salary.ToString("N0")</td>
                </tr>
            }
        </tbody>
    </table>
}

@code {
    private List<Employee>? employees;

    protected override async Task OnInitializedAsync()
    {
        employees = await EmployeeSvc.GetAllEmployeesAsync();
    }
}

Add navigation link

In Components/Layout/NavMenu.razor, add a link to your new page inside the <nav> element.

<div class="nav-item px-3">
    <NavLink class="nav-link" href="employees">
        <span class="bi bi-people-fill" aria-hidden="true"></span> Employees
    </NavLink>
</div>

You have now built a functional, read-only Blazor application that connects to an Oracle database and displays data in a table. This confirms that your core setup, including the Direct mode connection, dependency injection, and data retrieval, is working correctly.

Oracle database employee table

Insert Oracle data

We will now enhance the application by adding the ability to create new records. This involves adding an EditForm to the UI and implementing the corresponding logic to execute an INSERT SQL command. The new EMPLOYEE_ID is generated using a MAX()+1 subquery, which avoids the need to create a separate Oracle sequence object.

Update the data service (EmployeeService.cs)

Add the InsertEmployeeAsync method to your EmployeeService.cs file.

// Data/EmployeeService.cs
// ... (add this method inside the EmployeeService class)
public async Task InsertEmployeeAsync(Employee employee)
{
    using var connection = new OracleConnection(_connectionString);
    await connection.OpenAsync();
    using var command = new OracleCommand(
        "INSERT INTO EMPLOYEES (EMPLOYEE_ID, FIRST_NAME, LAST_NAME, EMAIL, HIRE_DATE, SALARY) " +
        "VALUES ((SELECT NVL(MAX(EMPLOYEE_ID),0)+1 FROM EMPLOYEES), :first_name, :last_name, :email, SYSDATE, :salary)",
        connection);
    command.Parameters.AddWithValue(":first_name", employee.FirstName);
    command.Parameters.AddWithValue(":last_name", employee.LastName);
    command.Parameters.AddWithValue(":email", employee.Email);
    command.Parameters.AddWithValue(":salary", employee.Salary);
    await command.ExecuteNonQueryAsync();
}

Update the UI (Employees.razor)

Modify Employees.razor to add an EditForm for creating new employees. Place this block above the data table.

<h3>Add New Employee</h3>
<EditForm Model="@newEmployee" OnValidSubmit="HandleInsert" FormName="NewEmployeeForm">
    <DataAnnotationsValidator />
    <ValidationSummary />

    <div class="mb-3">
        <label for="newFirstName" class="form-label">First Name</label>
        <InputText id="newFirstName" @bind-Value="newEmployee.FirstName" class="form-control" />
    </div>

    <div class="mb-3">
        <label for="newLastName" class="form-label">Last Name</label>
        <InputText id="newLastName" @bind-Value="newEmployee.LastName" class="form-control" />
    </div>

    <div class="mb-3">
        <label for="newEmail" class="form-label">Email</label>
        <InputText id="newEmail" @bind-Value="newEmployee.Email" class="form-control" />
    </div>

    <div class="mb-3">
        <label for="newSalary" class="form-label">Salary</label>
        <InputNumber id="newSalary" @bind-Value="newEmployee.Salary" class="form-control" />
    </div>

    <button type="submit" class="btn btn-primary">Insert Employee</button>
</EditForm>
<hr />
EditForm to create new employee

Update the UI logic (Employees.razor)

Modify the @code block to add the newEmployee field and the HandleInsert method. Also, refactor the data loading into a reusable LoadEmployees method.

@code {
    private List<Employee>? employees;
    private Employee newEmployee = new();

    protected override async Task OnInitializedAsync()
    {
        await LoadEmployees();
    }

    private async Task LoadEmployees()
    {
        employees = await EmployeeSvc.GetAllEmployeesAsync();
    }

    private async Task HandleInsert()
    {
        await EmployeeSvc.InsertEmployeeAsync(newEmployee);
        newEmployee = new(); // Clear the form after insert
        await LoadEmployees(); // Refresh the list
    }
}
Update Oracle database employee table

The application can now add new records to the database. Users can enter data in the form, press the Insert Employee button, and the table updates immediately with the new entry. The HIRE_DATE is set automatically to the current date via Oracle's SYSDATE function.

Add new record to Oracle database

Update Oracle data

In this step, we will implement the ability to edit existing records. This requires adding an Edit button to each table row and a second EditForm that appears when a record is selected for editing.

Update the data service (EmployeeService.cs)

Add the UpdateEmployeeAsync method to EmployeeService.cs.

// Data/EmployeeService.cs
// ... (add this method inside the EmployeeService class)
public async Task UpdateEmployeeAsync(Employee employee)
{
    using var connection = new OracleConnection(_connectionString);
    await connection.OpenAsync();
    using var command = new OracleCommand(
        "UPDATE EMPLOYEES SET FIRST_NAME = :first_name, LAST_NAME = :last_name, " +
        "EMAIL = :email, SALARY = :salary WHERE EMPLOYEE_ID = :employee_id",
        connection);
    command.Parameters.AddWithValue(":first_name", employee.FirstName);
    command.Parameters.AddWithValue(":last_name", employee.LastName);
    command.Parameters.AddWithValue(":email", employee.Email);
    command.Parameters.AddWithValue(":salary", employee.Salary);
    command.Parameters.AddWithValue(":employee_id", employee.EmployeeId);
    await command.ExecuteNonQueryAsync();
}

Update the UI (Employees.razor)

Add a conditional EditForm for editing. This form only appears when an employee is selected. Place it between the insert form and the table. Also, add an Edit button to each table row and an empty <th> for the actions column.

<!-- ... (After the 'Add New Employee' form and <hr />) ... -->

@if (employeeToEdit.EmployeeId != 0)
{
    <h3>Edit Employee</h3>
    <EditForm Model="@employeeToEdit" OnValidSubmit="HandleUpdate" FormName="EditEmployeeForm">
        <DataAnnotationsValidator />
        <ValidationSummary />

        <div class="mb-3">
            <label for="editFirstName" class="form-label">First Name</label>
            <InputText id="editFirstName" @bind-Value="employeeToEdit.FirstName" class="form-control" />
        </div>
        <div class="mb-3">
            <label for="editLastName" class="form-label">Last Name</label>
            <InputText id="editLastName" @bind-Value="employeeToEdit.LastName" class="form-control" />
        </div>
        <div class="mb-3">
            <label for="editEmail" class="form-label">Email</label>
            <InputText id="editEmail" @bind-Value="employeeToEdit.Email" class="form-control" />
        </div>
        <div class="mb-3">
            <label for="editSalary" class="form-label">Salary</label>
            <InputNumber id="editSalary" @bind-Value="employeeToEdit.Salary" class="form-control" />
        </div>
        <button type="submit" class="btn btn-success">Save</button>
        <button type="button" class="btn btn-secondary" @onclick="ClearForm">Cancel</button>
    </EditForm>
    <hr />
}

<!-- ... (In the table, add an actions column) ... -->
<th></th>

<!-- ... (In the foreach loop, add the Edit button) ... -->
<td>
    <button class="btn btn-sm btn-warning" @onclick="() => SetEmployeeForUpdate(emp)">Edit</button>
</td>
Edit the UI of the employee table

Update the UI logic (Employees.razor)

Add the employeeToEdit field and the SetEmployeeForUpdate, HandleUpdate, and ClearForm methods to the @code block.

@code {
    private List<Employee>? employees;
    private Employee newEmployee = new();
    private Employee employeeToEdit = new();

    // ... (existing OnInitializedAsync, LoadEmployees, HandleInsert methods) ...

    private void SetEmployeeForUpdate(Employee employee)
    {
        // Create a copy to avoid modifying the list directly
        employeeToEdit = new Employee
        {
            EmployeeId = employee.EmployeeId,
            FirstName = employee.FirstName,
            LastName = employee.LastName,
            Email = employee.Email,
            Salary = employee.Salary
        };
    }

    private async Task HandleUpdate()
    {
        await EmployeeSvc.UpdateEmployeeAsync(employeeToEdit);
        ClearForm();
        await LoadEmployees(); // Refresh the list
    }

    private void ClearForm()
    {
        employeeToEdit = new(); // Reset to hide the edit form
    }
}
Edit the UI of the employee table

The application now supports editing data. Users can click Edit on any employee, modify the employee's details in the form, and save the changes to the database. Selecting Cancel hides the edit form without saving.

Edit the UI of the employee table

Delete Oracle data

In the final step, we will implement the delete functionality. This involves adding a Delete button to each table row and using Blazor's JavaScript Interop to display a browser confirmation dialog before deleting the row.

Update the data service (EmployeeService.cs)

Add the DeleteEmployeeAsync method to EmployeeService.cs.

// Data/EmployeeService.cs
// ... (add this method inside the EmployeeService class)
    public async Task DeleteEmployeeAsync(int employeeId)
    {
        using var connection = new OracleConnection(_connectionString);
        await connection.OpenAsync();
        using var command = new OracleCommand(
            "DELETE FROM EMPLOYEES WHERE EMPLOYEE_ID = :employee_id",
            connection);
        command.Parameters.AddWithValue(":employee_id", employeeId);
        await command.ExecuteNonQueryAsync();
    }
Add a delete button to the employee table

Update the UI (Employees.razor)

First, inject the IJSRuntime service at the top of the file. Then add a Delete button next to the existing Edit button in each table row.

@inject IJSRuntime JSRuntime

<!-- ... (In the foreach loop, next to the Edit button) ... -->
<td>
    <button class="btn btn-sm btn-warning" @onclick="() => SetEmployeeForUpdate(emp)">Edit</button>
    <button class="btn btn-sm btn-danger" @onclick="() => HandleDelete(emp)">Delete</button>
</td>

Update the UI logic (Employees.razor)

Add the HandleDelete method to the @code block. This method invokes the browser's native confirm() dialog via JavaScript Interop. The record is only deleted if the user clicks OK.

// ... (add this method inside the @code block)
private async Task HandleDelete(Employee employee)
{
    bool confirmed = await JSRuntime.InvokeAsync<bool>("confirm",
        $"Are you sure you want to delete {employee.FirstName} {employee.LastName}?");
    if (confirmed)
    {
        await EmployeeSvc.DeleteEmployeeAsync(employee.EmployeeId);
        await LoadEmployees(); // Refresh the list
    }
}
Add a delete button to the employee table

You have now completed the Blazor application. It provides full CRUD functionality, allowing users to read, create, update, and delete records in the Oracle database through a modern web interface.

Add a delete button to the employee table

Video tutorial: How to Connect .NET Blazor Application to Oracle Database

Conclusion

In this tutorial, we explored how to establish a connection between a Blazor application and an Oracle database using dotConnect for Oracle. Together, we walked through, inserting data, retrieving records, and performing update and delete operations. Thus, the approach covered in this tutorial provides a solid foundation for building agile, data-driven applications that leverage data and integrate with Oracle databases.

FAQ

How do you install and activate dotConnect for Oracle in a .NET project?
Install dotConnect for Oracle via the EXE installer or by adding the Devart.Data.Oracle NuGet package to your project, then obtain your personal activation key from your Devart Customer Portal and include it in the connection string via the License Key parameter for a working connection.
How do you create a connection to Oracle using dotConnect in C#?
Define a connection string that includes host, user ID, password, database, and the License Key value, then create an OracleConnection instance with this string and call Open() for it inside a try-catch block to test and handle connection errors.
How do you enable encryption for secure Oracle connections with dotConnect?
Use Oracle Native Network Encryption by configuring encryption in the sqlnet.ora file on both client and server sides. No special parameters are required in the connection string.
Can you connect to Oracle using Entity Framework Core and dotConnect?
Yes, you can either use Entity Developer to visually create an EF Core model from the database or run Scaffold-DbContext with a dotConnect connection string (including License Key) to generate the DbContext and entity classes.
Is it possible to connect to Oracle using Visual Studio Server Explorer with dotConnect?
Yes, it is possible. All you need to do is navigate to Visual Studio Server Explorer, add a new Data Connection, choose dotConnect for Oracle as the data provider, enter your credentials, test the connection, and then browse Oracle data directly in Visual Studio.

Dereck Mushingairi

I'm a technical content writer who loves turning complex topics—think SQL, connectors, and backend chaos–into content that actually makes sense (and maybe even makes you smile). I write for devs, data folks, and curious minds who want less fluff and more clarity. When I'm not wrangling words, you'll find me dancing salsa, or hopping between cities.

Try the 30-day trial of the full product. No limits. No card required. Start free trial