databaseasp.net-corerazorblazordbcontext

Entity Framework delete by id (SQL and simple way)


I have been looking for deleting rows from a database with Blazor. I have been trying it but been having run into issues that require long code I want to keep it simple for my project.

My code:

@page "/database"
@attribute [StreamRendering]

@*Form*@
<div class="row">
    <div class="col-12">
        <div class="card">
            <div class="card-body">
                <h1 class="card-title text-center">DataBase Insert</h1>

                <EditForm Model="employee" OnValidSubmit="Submit" FormName="Person">
                    <DataAnnotationsValidator/>

                    <label>Name: </label>
                    <InputText placeholder="Name" class="form-control" @bind-Value="employee!.Name" aria-required="true" />
                    <ValidationMessage For="@(() => employee.Name)" />

                    <br />

                    <label>Age: </label>
                    <InputNumber placeholder="Age" class="form-control" @bind-Value="employee!.Age" aria-required="true" />
                    <ValidationMessage For="@(() => employee.Age)"  />

                    <br />

                    <label>Address: </label>
                    <InputText placeholder="Address" class="form-control" @bind-Value="employee!.HomeAddress" aria-required="true" />
                    <ValidationMessage For="@(() => employee.HomeAddress)" />

                    <br />

                    <label>WhereFrom: </label>
                    <InputText placeholder="WhereFrom?" class="form-control" @bind-Value="employee!.WhereFrom" aria-required="true" />
                    <ValidationMessage For="@(() => employee.WhereFrom)" />

                    <br />

                    <button type="submit" class="btn btn-primary btn-rounded" href="database">Submit</button>

                </EditForm>

            </div>
        </div>
    </div>
</div>

<br />
<br />

@*Database*@
<div class="row">
    <div class="col-12">
        <div class="card">
            <div class="card-body">
                <h1 class="card-title text-center">DataBase Table</h1>
                    @*Table*@
                    <table class="table table-bordered text-center">
                        <tr class="bg-dark text-white">
                            <td> ID </td>
                            <td> Name </td>
                            <td> Age </td>
                            <td> HomeAddress </td>
                            <td> WhereFrom </td>
                            <td></td>
                        </tr>
                            @foreach (var employees in Employees)
                            {
                            <tr>
                                <td>@employees.Id</td>
                                <td>@employees.Name</td>
                                <td>@employees.Age</td>
                                <td>@employees.HomeAddress</td>
                                <td>@employees.WhereFrom</td>
                                <td><button type="submit" class="btn btn-danger" @onclick="Delete" href="database">X</button></td>
                            </tr>
                            }
                    </table>
            </div>
        </div>
    </div>
</div>

@inject Data.AppDbContext dbContext

@code {
    [SupplyParameterFromForm]
    public Employee? employee { get; set; }
    public AppDbContext context;

    public int SetId { get; set; }

    List<Employee> Employees = new List<Employee>();

    protected override void OnInitialized()
    {
        // creates new employee null to fill in and sets the ID
        employee ??= new();

        // this gets the values from the database for the list 
        Employees = dbContext._Employee.ToList();
    }

    protected async void Delete()
    {
        DeleteFunc(employee!.Id);
        await dbContext.SaveChangesAsync();

        //update Database
        UpdateDatabase();
    }

    protected async void DeleteFunc(int Id)
    {
        var employee = await dbContext._Employee.FindAsync(Id);
        dbContext._Employee.Remove(employee);
    }

    private async Task Submit()
    {
        // this for database
        dbContext._Employee.Add(employee);
        await dbContext.SaveChangesAsync();

        // update database
        UpdateDatabase();
    }

    public void UpdateDatabase()
    {
        // this refreshes the data in the form
        employee = new Employee();

        // this is for list to update
        Employees.Clear();
        Employees = dbContext._Employee.ToList();

        StateHasChanged();
    }
}

I am trying to keep it simple and don't want all the different services and stuff just want a simple delete button that removes row from the database. If that's too much, I am open to longer code, but I want to try to avoid that.

What I want to do:

protected async void Delete()
{
    DeleteFunc(employee!.Id);
    await dbContext.SaveChangesAsync();

    // update database
    UpdateDatabase();
}

protected async void DeleteFunc(int Id)
{
    var employee = await dbContext._Employee.FindAsync(Id);
    dbContext._Employee.Remove(employee);
}

I am trying this out but it isn't working - can anyone give some suggestions as to why?


Solution

  • You can edit your delete button like this:

    <button type="button" class="btn btn-danger" @onclick="() => Delete(emp.Id)">X</button>
    

    The button's @onclick attribute uses a lambda expression () => Delete(employee.Id) to pass the current row's Id to the Delete method. The Delete method now takes an id parameter and finds the corresponding employee to delete.

    @code {
    [SupplyParameterFromForm]
    public Employee? employee { get; set; }
    public List<Employee> Employees { get; set; } = new List<Employee>();
    
    protected override async Task OnInitializedAsync()
    {
        employee ??= new Employee();
        UpdateDatabase();
    }
    
    private async Task Delete(int id)
    {
        var emp = await dbContext._Employee.FindAsync(id);
        if (emp != null)
        {
            dbContext._Employee.Remove(emp);
            await dbContext.SaveChangesAsync();
    
            UpdateDatabase();
        }
    }
    
    
    private async Task Submit()
    {
        if (employee != null)
        {
            dbContext._Employee.Add(employee);
            await dbContext.SaveChangesAsync();
    
            UpdateDatabase();
        }
    }
    
    private void UpdateDatabase()
    {
        Employees = dbContext._Employee.ToList();
        StateHasChanged();
    }
    

    }

    And if you use the blazor server, remember to add this line: @rendermode InteractiveServer to make the button work.

    Because, by default, it is in static mode (SSR), the onclick event may not respond; it will only succeed in interactive mode.

    refer to Build a full-stack web app with Blazor:

    Page content for interactive pages is prerendered, where content on the server is initially generated and sent to the client without enabling event handlers for rendered controls.

    If you don't want to use interactive mode, you can also do that by making the button a form submit method:

    <form method="post" @onsubmit="() => Delete(emp.Id)" @formname="@($"DeleteForm_{emp.Id}")">
        <AntiforgeryToken />
        <button type="submit" class="btn btn-danger">X</button>
    </form>
    

    this is my test result:

    result image