Oracle CRUD Operations in .NET MAUI

.NET MAUI (Multi-platform App UI) is a cross-platform framework for building desktop and mobile applications using C# and XAML. It allows creating applications running on Windows, macOS, and Andriod operating systems, all from one Codebase.

Oracle Database is a robust, commercial relational database management system (RDBMS) developed by Oracle Corporation. It delivers comprehensive SQL implementation, enterprise-grade scalability, built-in high availability, performance optimization, and extensive management tools. Thus, Oracle Database is a preferred choice for large organizations that require industrial-strength database solutions.

Why choose dotConnect for Oracle?

dotConnect for Oracle is an ideal data provider for all Oracle-related operations. It offers features like on-the-fly connector creation and flexible configuration, seamless integration into Visual Studio, and enhanced ORM support.

Download Now dotConnect for Oracle

Requirements

  • Visual Studio 2022: The IDE of choice. Download and install it if you don't have it. We're going to use the community version, so you can get it as well.
  • .NET MAUI: A .NET workload installable with the .NET CLI tool. It is available within the Visual Studio 2022 installer.
  • dotConnect for Oracle: A feature-rich ADO.NET provider with Entity Framework, NHibernate, and LinqConnect support.

Download and activate dotConnect for Oracle

For the trial version, simply download and install dotConnect for Oracle on your machine. No license key is required and you can start exploring the product immediately.

Purchase and access the full Version

After purchasing the full version, go to your profile's Licenses page. You'll find a list of your licenses, including dotConnect for Oracle purchase.

Click Details next to your dotConnect for Oracle license. Here, you'll find the license details and the Activation Key.

Purchase and access the full Version

Download the full version

To access the list of available product versions, click Download Product Versions. Select the most recent version and download the installer.

Download the full version

Execute the downloaded file and follow the on-screen instructions to install dotConnect for Oracle on your machine. This process will install the software and activate all features associated with your license key.

Create a .NET MAUI app project

In Visual Studio, click Create New Project. In the Search Template field, search for .NET MAUI App and click it.

MAUI template

Name your project, select .NET 8 as the target framework, and leave all the other options as the default values. Finally,
click Create.

Install packages

We will install dotConnect for Oracle to our project via the NuGet Package Manager in Visual Studio. In the taskbar, navigate to Tools > NuGet Package Manager > Manage NuGet Packages for Solution.

NuGet Package Manager

The NuGet Package Manager page opens. Click Browse and search for Devart.Data.Oracle. Then, select your project and
click Install.

Select the project

When you run the application, the scaffolded application will appear.

Create a MAUI test page

Next, create a new page where we'll do most of our work. Right-click the OracleMAUI solution and select Add New Item. Then select the .NET MAUI ContentPage(XAML) template, name this page OracleDemo.xaml, and click Add. Now, from the solution explorer, click the MainPage.xaml file and modify it to look as follows.

<ScrollView>
        <VerticalStackLayout
            Padding="30,0"
            Spacing="25">
            <Image
                Source="dotnet_bot.png"
                HeightRequest="185"
                Aspect="AspectFit"
                SemanticProperties.Description="dot net bot in a race car number eight" />

            <Label
                Text="Hello, World!"
                Style="{StaticResource Headline}"
                SemanticProperties.HeadingLevel="Level1" />

            <Label
                Text="Welcome to 
.NET Multi-platform App UI"
                Style="{StaticResource SubHeadline}"
                SemanticProperties.HeadingLevel="Level2"
                SemanticProperties.Description="Welcome to dot net Multi platform App U I" />

            <Button
                x:Name="CounterBtn"
                Text="Click me"
                SemanticProperties.Hint="Counts the number of times you click"
                Clicked="OnCounterClicked"
                HorizontalOptions="Fill" />

            <Button Text="Go to Actor Page"
            Clicked="OnNavigateButtonClicked"
            VerticalOptions="Center"
            HorizontalOptions="Center" />
        </VerticalStackLayout>
    </ScrollView>

We added a new button called Go to Actor Page to navigate to the created page. The final step here is to open MainPage.xaml.cs and add the OnNavigateButtonClicked method.

Right-click MainPage.xaml from the solution explorer and select View Code. Add this piece of code to the MainPage class.

 private async void OnNavigateButtonClicked(object sender, EventArgs e)
        {
            await Navigation.PushAsync(new OracleDemo());
        }

So, your MainPage.xaml.cs should look like this.

Mainpage file

When you run the application and click Go to Actor page, you should see the page we just created.

Create a connection to an Oracle database

To add the DatabaseConnectionClass class, paste the following code.

public static class DatabaseConnectionClass
    {
        public static string databasePath = "" +
	     "Direct=True;" +
	     "Host=127.0.0.1;" +
	     "ServiceName=XE;" +
	     "UserID=TestUser;" +
	     "Password=TestPassword";
        public static void CreateActorTable()
        {
            OracleConnection conn = new OracleConnection($"{databasePath};LicenseKey={LicenseKey.yourLicensekey};");
            OracleCommand cmd = new OracleCommand();
            cmd.CommandText = @"
        CREATE TABLE actor (
    actor_id NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    first_name VARCHAR2(50) NOT NULL,
    last_name VARCHAR2(50) NOT NULL,
    last_update TIMESTAMP DEFAULT SYSTIMESTAMP
)";
            cmd.Connection = conn;
            conn.Open();
            try
            {
                cmd.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"An error occured; {ex.Message}");
            }
        }
    }

Thus, we added a method that creates the actor table. In the connection strings, we specified the location of the database and the dotConnect for Oracle license key defined in another class. Next, in OracleDemo.xaml.cs, add the following code to define the method that will be called when the page opens.

public partial class OracleDemo : ContentPage
{
	public OracleDemo()
	{
		InitializeComponent();
        DatabaseConnectionClass.CreateActorTable();
    }
}

To call the method for creating the table, run the application and click Go to Actor page. Since we created the table, you can comment out the CreateActorTable method.

Homepage

INSERT Oracle data

Let's add some data from the application to the table. For this, create a class based on the created table. Right-click your solution and paste this code to include the Actor.cs class.

public class Actor
    {
        public int ActorId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public DateTime LastUpdate { get; set; }
    }

Next, in DatabaseConnectionClass, add a new method.

public static void AddActor(Actor actor)
{
    OracleConnection conn = new OracleConnection($"{databasePath};LicenseKey={LicenseKey.yourLicensekey};");
    OracleCommand cmd = new OracleCommand();
    cmd.CommandText = "INSERT INTO actor (first_name, last_name, last_update) VALUES (:first_name, :last_name, :last_update)";
    cmd.Parameters.Add(new OracleParameter("first_name", actor.FirstName));
    cmd.Parameters.Add(new OracleParameter("last_name", actor.LastName));
    cmd.Parameters.Add(new OracleParameter("last_update", actor.LastUpdate));
    cmd.Connection = conn;
    conn.Open();
    try
    {
        cmd.ExecuteNonQuery();
    }
    catch (Exception ex)
    {
        Console.WriteLine($"An error occured; {ex.Message}");
    }
}

To configure the application's view, modify OracleDemo.xaml so it looks like this.

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="OracleMAUI.OracleDemo"
             Title="OracleDemo">
    <StackLayout>
        <StackLayout x:Name="InsertSection" IsVisible="False" Padding="10">
            <Label Text="First Name:" />
            <Entry x:Name="InsertFirstNameEntry" Placeholder="Enter first name" />
            <Label Text="Second Name:" />
            <Entry x:Name="InsertSecondNameEntry" Placeholder="Enter second name" />
            <Label x:Name="InsertErrorLabel" TextColor="Red" IsVisible="False" />
            <Button Text="Insert" Clicked="OnInsertButtonClicked" WidthRequest="80" />
        </StackLayout>
        <Button x:Name="InsertActor" Text="Insert New Actor" Clicked="OnShowInsertSectionClicked" WidthRequest="150" />
    </StackLayout>
</ContentPage>

Then, in the OracleDemo.xaml.cs code-behind file, add these two methods within the OracleDemo class.

private void OnShowInsertSectionClicked(object sender, EventArgs e)
{
    InsertFirstNameEntry.Text = string.Empty;
    InsertSecondNameEntry.Text = string.Empty;

    // Show the insert section and hide the Insert actor button
    InsertSection.IsVisible = true;
    InsertActor.IsVisible = false;
}
private void OnInsertButtonClicked(object sender, EventArgs e)
{
    if (string.IsNullOrWhiteSpace(InsertFirstNameEntry.Text) ||
           string.IsNullOrWhiteSpace(InsertSecondNameEntry.Text))
    {
        // Show error message
        InsertErrorLabel.Text = "Both fields are required.";
        InsertErrorLabel.IsVisible = true;
        return;
    }
    // Create a new actor object with the inserted values
    var newActor = new Actor
    {
        FirstName = InsertFirstNameEntry.Text,
        LastName = InsertSecondNameEntry.Text,
        LastUpdate = DateTime.Now
    };
    // Add the new actor to the database
    DatabaseConnectionClass.AddActor(newActor);

    // Refresh the CollectionView
    BindingContext = null;
    BindingContext = this;

    // Hide the insert section
    InsertSection.IsVisible = false;
}

Now, run the code and click Go to Actor page.

Run the code

Click Insert New Actor, enter the actor's first and last names, and click Insert.

Click Insert

Read Oracle data

As we inserted the record into the table, we need a way to view what was added. In DataBaseConnectionClass, add this new method to get a list of all actors.

public static List GetActors()
  {
      List actors = new List();
      OracleConnection conn = new OracleConnection($"{databasePath};LicenseKey={LicenseKey.yourLicensekey};");
      OracleCommand cmd = new();
      cmd.CommandText = "SELECT * FROM actor;";
      cmd.Connection = conn;
      conn.Open();
      OracleDataReader reader = cmd.ExecuteReader();
      while (reader.Read())
      {
          Actor actor = new Actor
          {
              ActorId = Convert.ToInt32(reader["actor_id"]),
              FirstName = reader["first_name"].ToString(),
              LastName = reader["last_name"].ToString(),
              LastUpdate = Convert.ToDateTime(reader["last_update"])
          };
          actors.Add(actor);
      }
      return actors;
  }

Edit OracleDemo.xaml to make it look like this.

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="OracleMAUI.OracleDemo"
             Title="OracleDemo">
    <StackLayout>
        <CollectionView ItemsSource="{Binding Actors}">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <Grid Padding="2" RowDefinitions="Auto">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="50" />
                            <ColumnDefinition Width="100" />
                            <ColumnDefinition Width="100" />
                            <ColumnDefinition Width="100" />
                        </Grid.ColumnDefinitions>

                        <Label Text="{Binding ActorId}" 
                         Grid.Column="0"                         
                         VerticalOptions="Center"
                         HorizontalOptions="Center"
                         Padding="3" 
                         Margin="0.5" />


                        <Label Text="{Binding FirstName}" 
                         Grid.Column="1" 
                         VerticalOptions="Center"
                         HorizontalOptions="Center"
                         Padding="3" 
                         Margin="0.5" />

                        <Label Text="{Binding LastName}" 
                         Grid.Column="2" 
                         VerticalOptions="Center"
                         HorizontalOptions="Center"
                         Padding="3" 
                         Margin="0.5" />

                        <Label Text="{Binding LastUpdate}" 
                        Grid.Column="3" 
                        VerticalOptions="Center"
                        HorizontalOptions="Center"
                        Padding="3" 
                        Margin="0.5" />
                    </Grid>

                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>

        <StackLayout x:Name="InsertSection" IsVisible="False" Padding="10">
            <Label Text="First Name:" />
            <Entry x:Name="InsertFirstNameEntry" Placeholder="Enter first name" />
            <Label Text="Second Name:" />
            <Entry x:Name="InsertSecondNameEntry" Placeholder="Enter second name" />
            <Label x:Name="InsertErrorLabel" TextColor="Red" IsVisible="False" />
            <Button Text="Insert" Clicked="OnInsertButtonClicked" WidthRequest="80" />
        </StackLayout>
        <Button x:Name="InsertActor" Text="Insert New Actor" Clicked="OnShowInsertSectionClicked" WidthRequest="150" />
    </StackLayout>

</ContentPage>

Then, in the OracleDemo.xaml.cs file, add a new property for a list of actors. Initialize it in the class constructor and set the binding to this property.

public partial class OracleDemo : ContentPage
{
    public List Actors { get; set; }
    public OracleDemo()
	{
	  InitializeComponent();
        //DatabaseConnectionClass.CreateActorTable();
        Actors = DatabaseConnectionClass.GetActors();
        // Set the BindingContext
        BindingContext = this;
    }
.....
}

To check the data, run the application and navigate to OracleDemo.

Click Insert

UPDATE Oracle data

Let's look at how to change Seth's last name. This example will likely be useful for your application. In DataBaseConnectionClass, create a new method called UpdateActor.

public static void UpdateActor(Actor actor)
        {
            OracleConnection conn = new OracleConnection($"{databasePath};LicenseKey={LicenseKey.yourLicensekey};");
            OracleCommand cmd = new OracleCommand();
            cmd.CommandText = "UPDATE actor SET first_name = :first_name, last_name = :last_name, last_update = :last_update WHERE actor_id = :actor_id";
            cmd.Parameters.Add(new OracleParameter("first_name", actor.FirstName));
            cmd.Parameters.Add(new OracleParameter("last_name", actor.LastName));
            cmd.Parameters.Add(new OracleParameter("last_update", actor.LastUpdate));
            cmd.Parameters.Add(new OracleParameter("actor_id", actor.ActorId));
            cmd.Connection = conn;
            conn.Open();
            try
            {
                cmd.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"An error occured; {ex.Message}");
            }
        }

Next, in the OracleDemo.xaml file, replace the existing code with the following to add the Update button and a section for inserting the updated values.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="OracleMAUI.OracleDemo"
             Title="OracleDemo">
    <StackLayout>
        <CollectionView ItemsSource="{Binding Actors}">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <Grid Padding="2" RowDefinitions="Auto">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="50" />
                            <ColumnDefinition Width="100" />
                            <ColumnDefinition Width="100" />
                            <ColumnDefinition Width="100" />
                            <ColumnDefinition Width="Auto" />
                        </Grid.ColumnDefinitions>

                        <Label Text="{Binding ActorId}" 
                         Grid.Column="0"                         
                         VerticalOptions="Center"
                         HorizontalOptions="Center"
                         Padding="3" 
                         Margin="0.5" />

                        <Label Text="{Binding FirstName}" 
                         Grid.Column="1" 
                         VerticalOptions="Center"
                         HorizontalOptions="Center"
                         Padding="3" 
                         Margin="0.5" />

                        <Label Text="{Binding LastName}" 
                         Grid.Column="2" 
                         VerticalOptions="Center"
                         HorizontalOptions="Center"
                         Padding="3" 
                         Margin="0.5" />

                        <Label Text="{Binding LastUpdate}" 
                        Grid.Column="3" 
                        VerticalOptions="Center"
                        HorizontalOptions="Center"
                        Padding="3" 
                        Margin="0.5" />

                        <Button Text="Update" 
                        Grid.Column="4" 
                        VerticalOptions="Center"
                        HorizontalOptions="Center"
                        Clicked="OnUpdateButtonClicked" 
                        CommandParameter="{Binding ActorId}" />
                    </Grid>

                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>

        <StackLayout x:Name="UpdateSection" IsVisible="False" Padding="10">
            <Label Text="Update First Name:" />
            <Entry x:Name="UpdateFirstNameEntry" Placeholder="Enter new first name" />
            <Label Text="Update Second Name:" />
            <Entry x:Name="UpdateSecondNameEntry" Placeholder="Enter new Last name" />
            <Label x:Name="UpdateErrorLabel" TextColor="Red" IsVisible="False" />
            <Button Text="Go" Clicked="OnGoButtonClicked" />
        </StackLayout>

        <StackLayout x:Name="InsertSection" IsVisible="False" Padding="10">
            <Label Text="First Name:" />
            <Entry x:Name="InsertFirstNameEntry" Placeholder="Enter first name" />
            <Label Text="Second Name:" />
            <Entry x:Name="InsertSecondNameEntry" Placeholder="Enter second name" />
            <Label x:Name="InsertErrorLabel" TextColor="Red" IsVisible="False" />
            <Button Text="Insert" Clicked="OnInsertButtonClicked" WidthRequest="80" />
        </StackLayout>
        <Button x:Name="InsertActor" Text="Insert New Actor" Clicked="OnShowInsertSectionClicked" WidthRequest="150" />
    </StackLayout>
</ContentPage>

In OracleDemo.xaml.cs, add a new property.

private Actor? _selectedActor;

We created in the XAML file two methods: OnUpdateButtonClicked and OnGoButtonClicked.

private void OnUpdateButtonClicked(object sender, EventArgs e)
    {
        var button = sender as Button;
        var actorId = (int)button.CommandParameter;

        // Find the actor in the list by ID
        _selectedActor = Actors.FirstOrDefault(p => p.ActorId == actorId);

        if (_selectedActor != null)
        {
            // Populate Entry fields with existing values

            UpdateFirstNameEntry.Text = _selectedActor.FirstName;
            UpdateSecondNameEntry.Text = _selectedActor.LastName;

            // Show the update section
            UpdateSection.IsVisible = true;
        }
    }
    private void OnGoButtonClicked(object sender, EventArgs e)
    {
        if (string.IsNullOrWhiteSpace(UpdateFirstNameEntry.Text) ||
               string.IsNullOrWhiteSpace(UpdateSecondNameEntry.Text))
        {
            // Show error message
            UpdateErrorLabel.Text = "Both fields are required.";
            UpdateErrorLabel.IsVisible = true;
            return;
        }

        if (_selectedActor != null)
        {
            // Create a new actor object with the updated values
            var updatedActor = new Actor
            {
                ActorId = _selectedActor.ActorId,
                FirstName = UpdateFirstNameEntry.Text,
                LastName = UpdateSecondNameEntry.Text,
                LastUpdate = DateTime.Now
            };

            // Update the actor in the database
            DatabaseConnectionClass.UpdateActor(updatedActor);

            // Hide the update section
            UpdateSection.IsVisible = false;
        }
    }

When you run the code, you'll see a new Update button.

Update button

Clicking the button opens an insert modal where you can input new values.

Insert new values

To update a record, click Go.

Update the record

DELETE Oracle data

Let's try deleting an actor from the database. For reference, we added a new actor, Johnny Blaze, to be removed.

New actor

In DataBaseConnectionClass, add the DeleteActor method.

public static void DeleteActor(int actorId)
{
    OracleConnection conn = new OracleConnection($"{databasePath};LicenseKey={LicenseKey.yourLicensekey};");
    OracleCommand cmd = new OracleCommand();
    cmd.CommandText = "DELETE FROM actor WHERE actor_id = :actor_id";
    cmd.Parameters.Add(new OracleParameter("actor_id", actorId));
    cmd.Connection = conn;
    conn.Open();
    try
    {
        cmd.ExecuteNonQuery();
    }
    catch (Exception ex)
    {
        Console.WriteLine($"An error occured; {ex.Message}");
    }
}

Then, in OracleDemo.xaml, add a new button under <Button Text="Update".

<Button Text="Delete" 
 Grid.Column="5" 
 VerticalOptions="Center"
 HorizontalOptions="Center"
 Clicked="OnDeleteButtonClicked" 
 CommandParameter="{Binding ActorId}" />

After that, add a new column definition in <Grid.ColumnDefinitions>.

<ColumnDefinition Width="Auto" />

Now, in OracleDemo.xaml.cs, add the method for OnDeleteButtonClicked that we created in the XAML file above.

private void OnDeleteButtonClicked(object sender, EventArgs e)
{
    var button = sender as Button;
    var actorId = (int)button.CommandParameter;

    // Find the actor in the database by ID
    DatabaseConnectionClass.DeleteActor(actorId);

    this.Actors = DatabaseConnectionClass.GetActors();

    BindingContext = null;
    BindingContext = this;
}

When you run the application, the Delete button will appear.

Delete button

To delete Johnny Blaze's record, click the button.

Delete the record

Video tutorial: How to connect .NET MAUI application to Oracle database

Conclusion

In this guide, we've explored how to perform essential CRUD operations using Oracle in a .NET MAUI application. With these steps, you can gain a foundational understanding of how to expand your app's functionality and interact with complex data. Continue experimenting with these operations to build, optimize, and customize your applications to meet new data needs.

dotConnect for Oracle

Get an enhanced ORM-enabled data provider for Oracle and develop .NET applications working with Oracle data quickly and easily!