Quantcast
Channel: Active questions tagged blazor - Stack Overflow
Viewing all articles
Browse latest Browse all 4839

DbContext is disposed after navigate

$
0
0

I'm developing a blazor web app and I'm facing a weird behaviour. Almost all pages are a copy/paste, they have CRUD operations and a previous list of differents elements (seasons, player, fixtures, etc...) but only in one of them I'm having problems. When I click on the 'Edit' button of a player I'm getting a 'Cannot access a disposed object' referring to the _dbContext.

Adding a breakpoint to the DisposeAsync() method I've discovered that it's been fired when I navigate to the edit page. But only happens in player's page, not in any of the other pages.

Here's the players page:

@page "/players"@attribute [Authorize]@using Models = Biwenger.Models@using Biwenger.Services@inject PlayersService service;@inject NavigationManager navigationManager;<h3>Jugadores</h3><a class="btn btn-primary" href="/player" role="button">Añadir</a><div class="mb-3 lg-6"><label for="search" class="form-label">Buscar Jugador:</label><input type="text" id="search" class="form-control" @bind="searchTerm" @oninput="FilterPlayers" placeholder="Escribe el nombre del jugador..." /></div><table class="table"><thead><tr><th scope="col">#</th><th scope="col">Nombre</th><th scope="col">Equipo</th><th scope="col">Acciones</th></tr></thead><tbody>        @if (filteredList.Count > 0)        {            foreach (var item in filteredList)            {<tr><th scope="row">@item.Id</th><td>@item.Name</td><td>@item.Team.Name</td><td><button type="button" class="btn btn-primary" @onclick="() => EditPlayer(item.Id, item.TeamId)">Editar</button></td></tr>            }        }        else        {<tr><td colspan="4" class="text-center">No hay registros.</td></tr>        }</tbody></table>@code {    List<Models.Player> fullList = new List<Models.Player>();    List<Models.Player> filteredList = new List<Models.Player>();    string searchTerm = "";    protected override async Task OnInitializedAsync()    {        fullList = await service.GetAllPlayers();        filteredList = fullList;    }    private void FilterPlayers()    {        if (string.IsNullOrEmpty(searchTerm))        {            filteredList = fullList;        } else        {            filteredList = fullList.Where(p => p.Name.Contains(searchTerm, StringComparison.OrdinalIgnoreCase))                .ToList();        }        StateHasChanged();    }    private void EditPlayer(int id, int teamId)    {        navigationManager.NavigateTo($"/player/{id}/{teamId}");  <-- Here calls for dispose    }}

This is the page I'm navigating to:

@page "/player/{id:int?}/{teamId:int?}"@attribute [Authorize]@using Biwenger.Models.ViewModels@using Biwenger.Services@inject ILogger<Player> Logger@inject PlayersService service@inject TeamsService teamsService@inject SeasonsService seasonsService;@inject NavigationManager navigationManager@inject IJSRuntime JS<PageTitle>Equipo</PageTitle><h3>@(model?.PlayerId == 0 ? "Nuevo Jugador" : "Editar Jugador")</h3><EditForm EditContext="editContext" OnValidSubmit="Submit" FormName="form"><DataAnnotationsValidator /><div class="col-mb-3 col-lg-6 col-md-6"><label for="name" class="form-label">Nombre</label><input id="name" class="form-control" @bind="model!.Name" @onblur="CheckIfNameExists" @ref="nameInput"></input></div><div class="col-mb-3 col-lg-6"><ValidationMessage For="() => model!.Name"></ValidationMessage></div><div class="col-mb-3 col-lg-6 col-md-6"><label for="team" class="form-label">Equipo</label><InputSelect id="team" class="form-control" @bind-Value="model!.TeamId"><option value="">Seleccione un equipo</option>            @foreach (Models.Team team in listTeams)            {<option value="@(team.Id)">@team.Name</option>            }</InputSelect></div><div class="col-mb-3 col-lg-6"><ValidationMessage For="() => model!.TeamId"></ValidationMessage></div><div class="col-mb-3 col-lg-6 col-md-6"><label for="team" class="form-label">Posición</label>        @if (positionsItems != null)        {<BootstrapSelect            TItem="Models.DropdownItem<String>"            Data="@positionsItems"            @bind-Value="model!.Position"            TextField="@((item) => item.Value)"            ValueField="@((item) => item.Key.ToString())"            TType="Biwenger.Enums.Positions"></BootstrapSelect>        }</div><div class="col-mb-3 col-lg-6"><ValidationMessage For="() => model!.TeamId"></ValidationMessage></div><div class="col-mb-3 col-lg-6 col-md-6"><label for="cost" class="form-label">Coste @currentSeason!.Name</label><input type="number" id="cost" @bind="currentPlayerCost!.Cost" min="1" class="form-control text-end" @ref="costInput" @onfocus="selectAllText" @onblur="addMillions" /></div><div class="form-check"><input class="form-check-input" type="checkbox" value="@model!.Black" id="checkBlack" @bind="model!.Black" /><label class="form-check-label" for="checkBlack"> Es negro</label></div><div class="form-check"><input class="form-check-input" type="checkbox" value="@model!.Active" id="checkActive" @bind="model!.Active" /><label class="form-check-label" for="checkActive"> Activo</label></div><div class="col-mb-3 col-lg-6"><button type="button" class="btn btn-secondary ms-2" @onclick="GoBack">Volver</button><button type="submit" class="btn @buttonClass" disabled="@(!editContext?.Validate() ?? false || isLoading)">            @if (isLoading)            {<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span><span class="visually-hidden">Enviando...</span>            }            else if (showSuccess)            {<span>Guardado...</span>            }            else if (showError)            {<span>Error...</span>            }            else            {<span>Enviar</span>            }</button></div></EditForm>@code {    private EditContext? editContext;    private ElementReference nameInput;    private ElementReference costInput;    private Biwenger.Models.Season? currentSeason;    private Biwenger.Models.PlayerSeasonCost? currentPlayerCost;    [Parameter]    public int? id { get; set; }    [Parameter]    public int? teamId { get; set; }    [SupplyParameterFromForm]    private PlayerWithCostViewModel? model { get; set; }    private List<Models.Team> listTeams = new List<Models.Team>();    private ValidationMessageStore? messageStore;    private bool isLoading = false;    private bool showSuccess = false;    private bool showError = false;    private string buttonClassSuccess = "btn-success";    private string buttonClassError = "btn-danger";    private string buttonClassIdle = "btn-primary";    private string buttonClass = "btn-primary";    IList<Models.DropdownItem<String>> positionsItems;    protected override async Task OnInitializedAsync()    {        positionsItems = new List<Models.DropdownItem<String>>        {            new Models.DropdownItem<String> { Key = 0, Value = "Posición" },            new Models.DropdownItem<String> { Key = 1, Value = "PT" },            new Models.DropdownItem<String> { Key = 2, Value = "DF" },            new Models.DropdownItem<String> { Key = 3, Value = "MC" },            new Models.DropdownItem<String> { Key = 4, Value = "DL" },        };        editContext = new EditContext(model ??= new PlayerWithCostViewModel());        currentSeason = seasonsService.GetCurrentSeason();        currentPlayerCost = new Models.PlayerSeasonCost();        listTeams = await teamsService.GetAllTeams();        if (id.HasValue && id.Value > 0)        {            model = await service.GetPlayerWithCostById(id.Value, teamId!.Value);            if (model != null)            {                editContext = new EditContext(model);            }        }        messageStore = new ValidationMessageStore(editContext);    }    private async void CheckIfNameExists()    {        if (!string.IsNullOrEmpty(model!.Name))        {            bool exists = await service!.NameExists(model!.Name, id, model!.TeamId);            messageStore?.Clear(() => model.Name);            if (exists)            {                messageStore?.Clear();                messageStore?.Add(() => model.Name, "El nombre ya existe");            }            editContext?.NotifyValidationStateChanged();        }    }    private void GoBack()    {        navigationManager.NavigateTo("/players");    }    private async Task Submit()    {        isLoading = true;        Logger.LogInformation("Se ha llamado a submit");        bool success = false;        if (editContext!.Validate())        {            if (id.HasValue && id.Value > 0)            {                success = await service.UpdatePlayer(model!, currentSeason!.Id);            }            else            {                if (model!.Costs!.Count == 0)                {                    model!.Costs.Add(new Models.PlayerSeasonCost()                        {                            Cost = currentPlayerCost!.Cost,                            SeasonId = currentSeason!.Id,                            TeamId = model!.TeamId                        });                }                success = await service!.AddPlayer(model!);            }            isLoading = false;            if (success)            {                showSuccess = true;                buttonClass = buttonClassSuccess;                StateHasChanged();                await Task.Delay(3000);                showSuccess = false;                buttonClass = buttonClassIdle;                StateHasChanged();                if (!id.HasValue)                {                    model = new PlayerWithCostViewModel();                    editContext = new EditContext(model);                    messageStore = new ValidationMessageStore(editContext);                    messageStore.Clear();                }                model!.Name = "";                model.TeamId = 0;                currentPlayerCost = new Models.PlayerSeasonCost();                model!.Black = false;                model!.Active = true;                StateHasChanged();                await JS.InvokeVoidAsync("focusElement", nameInput);            }            else            {                showSuccess = true;                buttonClass = buttonClassError;                await Task.Delay(1000);                showSuccess = false;                buttonClass = buttonClassIdle;            }        }    }    private async Task selectAllText()    {        await JS.InvokeVoidAsync("selectElementText", costInput);    }    private void addMillions()    {        if (currentPlayerCost!.Cost < 100)        {            currentPlayerCost.Cost = currentPlayerCost.Cost * 1000000;        }    }}

And the playersService:

using Biwenger.Data;using Biwenger.Models;using Biwenger.Models.ViewModels;using Microsoft.EntityFrameworkCore;namespace Biwenger.Services{    public class PlayersService    {        private readonly ApplicationDbContext _dbContext;        public PlayersService(ApplicationDbContext dbContext)        {            _dbContext = dbContext;        }        public async Task<List<Player>> GetAllPlayers()        {            return await _dbContext.Players.Include(p => p.Team).AsNoTracking().ToListAsync();        }        public async Task<List<Player>> GetAllActivePlayers()        {            return await _dbContext.Players.Where(p => p.Active == true).AsNoTracking().ToListAsync();        }        public async Task<bool> AddPlayer(PlayerWithCostViewModel player)        {            var strategy = _dbContext.Database.CreateExecutionStrategy();            bool result = false;            await strategy.ExecuteAsync(async () =>            {                var transaction = await _dbContext.Database.BeginTransactionAsync();                try                {                    var newPlayer = new Player                    {                        Active = player.Active,                        Black = player.Black,                        TeamId = player.TeamId,                        Name = player.Name,                        Position = player.Position,                    };                    await _dbContext.Players.AddAsync(newPlayer);                    var playerSeasonCost = new PlayerSeasonCost                    {                        Cost = player.Costs!.First().Cost,                        TeamId = player.TeamId,                        PlayerId = newPlayer.Id,                        SeasonId = player.Costs!.First().SeasonId,                    };                    await _dbContext.PlayersSeasonsCost.AddAsync(playerSeasonCost);                    await _dbContext.SaveChangesAsync();                    await transaction.CommitAsync();                    result = true;                }                catch (Exception ex)                {                    await transaction.RollbackAsync();                    result = false;                }            });            return result;        }        public async Task<bool> UpdatePlayer(PlayerWithCostViewModel player, int seasonId)        {            Player? currentPlayer = await _dbContext.Players.FindAsync(player.PlayerId);            if (currentPlayer == null)            {                return false;            }            var transaction = await _dbContext.Database.BeginTransactionAsync();            try            {                currentPlayer.Name = player.Name;                currentPlayer.Black = player.Black;                currentPlayer.Position = player.Position;                currentPlayer.Active = player.Active;                currentPlayer.TeamId = player.TeamId;                _dbContext.Players.Update(currentPlayer);                await _dbContext.SaveChangesAsync();                await transaction.CommitAsync();                return true;            }            catch (Exception ex)            {                await transaction.RollbackAsync();                return false;            }        }        public async Task<Player?> GetPlayerByid(int id)        {            return await _dbContext.Players.FindAsync(id);        }        public async Task<PlayerWithCostViewModel?> GetPlayerWithCostById(int playerId, int teamId)        {            try            {                Player? player = await _dbContext.Players                    .Include(p => p.PlayersSeasonsCost)                    .Where(p => p.Id == playerId && p.TeamId == teamId)                    .FirstOrDefaultAsync(); <-- Already _dbContext Disposed                if (player == null)                {                    return null;                }                List<PlayerSeasonCost>? pscList = await _dbContext.PlayersSeasonsCost.Where(psc => psc.PlayerId == playerId).AsNoTracking().ToListAsync();                PlayerWithCostViewModel pwcvm = new PlayerWithCostViewModel                {                    PlayerId = playerId,                    TeamId = teamId,                    Active = player.Active,                    Black = player.Black,                    Position = player.Position,                    Name = player.Name,                    Costs = pscList ??= new List<PlayerSeasonCost>()                };                return pwcvm;            }            catch (Exception ex)            {                Console.WriteLine(ex.Message);                return null;            }        }        public async Task<bool> NameExists(string name, int? id, int teamId)        {            if (id.HasValue && id.Value > 0)            {                return await _dbContext.Players.AnyAsync(t => t.Name == name && t.TeamId == teamId && t.Id != id);            }            return await _dbContext.Players.AnyAsync(t => t.Name == name && t.TeamId == teamId);        }        public async Task<List<PlayerWithCurrentCostVM>> GetPlayersWithCurrentCost()        {            List<PlayerWithCurrentCostVM> pwcc = new List<PlayerWithCurrentCostVM>();            pwcc = await _dbContext.Players.Include(p => p.PlayersSeasonsCost)                    .ThenInclude(psc => psc.Season)                    .Where(p => p.Active == true)                    .Select(p => new PlayerWithCurrentCostVM                    {                        Player = p,                        Name = p.Name,                        Cost = p.PlayersSeasonsCost == null ? 0 : p.PlayersSeasonsCost.Where(psc => psc.Season.Active == true).First().Cost                    })                     .AsNoTracking()                    .ToListAsync();            return pwcc;        }    }}

Viewing all articles
Browse latest Browse all 4839

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>