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

What is correct way to Add/Update entity with EF Core?

$
0
0

I have the following classes within my Blazor Web App .NET 8 project with Entity Framework Core:

public class Meeting : BaseModel{    public int Id { get; set; }    public string Name { get; set; }    public DateTime DateTime { get; set; }    public List<BoardMember>? BoardMembers { get; set; }    public List<DebtorContact>? DebtorAttendees { get; set; }    public List<Meeting>? ParentMeeting { get; set; }    public List<Meeting>? ChildMeetings { get; set; }}
public class DebtorContact : Person{    public int Id { get; set; }    public int DebtorId { get; set; }    public Debtor Debtor { get; set; }    public List<Meeting>? Meetings { get; set; }}

This it the code of my AppUpdate.razor page:

<EditForm class="" Model="@_meeting" OnValidSubmit="HandleSubmit"><div class="tab-section mt-5"><ul class="nav nav-justified nav-tabs tab-header" role="tablist"><li class="nav-item"><a class="nav-link active" data-toggle="tab" href="#general" role="tab">                    Gegevens</a></li></ul><div class="tab-content user-select-none"><div id="general" class="tab-pane fade show active" role="tabpanel"><div class="p-3 FormForNew"><DataAnnotationsValidator /><div class="form-group mb-3 custom-control custom-checkbox user-select-none"><InputCheckbox disabled="@(_disableButtonClicks)" class="custom-control-input" id="IsBoardMeeting" @bind-Value="@_meeting.IsBoardMeeting"></InputCheckbox><label class="custom-control-label" for="IsBoardMeeting">Deze vergadering is een bestuursvergadering</label></div><div class="form-group mb-3"><label for="Name">Naam*</label><InputText disabled="@(_disableButtonClicks)" class="form-control" id="Name" @bind-Value="@_meeting.Name"></InputText><ValidationMessage For="() => _meeting.Name" /></div><div class="row"><div class="col-6"><div class="form-group mb-3"><label for="DateTime">Datum*</label><InputDate class="form-control" id="DateTime" @bind-Value="@_meeting.DateTime"></InputDate><ValidationMessage For="() => _meeting.DateTime" /></div></div><div class="col-6"><div class="form-group ms-lg-3 mb-3"><label for="Time">Tijd*</label><input @bind-value="@Time" required type="time" id="Time" class="form-control valid" /></div></div></div><br /><p><u><b>Bestuursleden aanwezig:</b></u></p>                    @foreach (var member in _boardMembers.Where(x => x.IsActive || (_meeting.BoardMembers is object && _meeting.BoardMembers.Any(y => y.Id == x.Id))))                    {<InputCheckbox @bind-Value="@member.IsChecked" type="checkbox" class="custom-control-input" id="@(member.Name.Replace(" ", ""))" /><label class="custom-control-label" for="@(member.Name.Replace(" ", ""))">@(member.Name)</label><br />                    }<br /><br /><p><u><b>Externe aanwezig:</b></u></p><div class="form-group mb-3"><label for="DebName">Contactpersoon zoeken</label><input class="form-control" id="DebName" @bind="DebtorContactName" @bind:event="oninput"></input>                        @if (_debtorContactResults is object && _debtorContactResults.Count() > 0)                        {<div style="position: relative;width: 100%;"><div class="search-result-box">                                    @foreach (var contact in _debtorContactResults.Take(5))                                    {<div @onclick="() => DebtorContactClicked(contact)" class="result">@(contact.Name +" (" + contact.Debtor.Name +")")</div>                                    }                                    @if (_debtorContactResults.Count > 5)                                    {<div class="p-2 user-select-none" style="border-top: 1px solid #bbbbbb;text-align:center;font-size:12px;font-weight:bold;"><i>Er zijn meer resultaten beschikbaar. Er worden nu 5 resultaten getoond. Begin met typen om de lijst met resultaten te verfijnen.</i></div>                                    }<button class="mb-2 ms-2" style="text-decoration:underline;" @onclick="async () => await AddUpdateDebtorContact()">Nieuw contactpersoon toevoegen</button></div></div>                        }                        else if ((_debtorContactResults is not object || _debtorContactResults.Count() == 0) && DebtorContactName != "")                        {<div style="position: relative;width: 100%;"><div class="search-result-box"><button class="mb-2 ms-2 mt-2" style="text-decoration:underline;" @onclick="async () => await AddUpdateDebtorContact()">Nieuw contactpersoon toevoegen</button></div></div>                        }</div>                    @if (_debtorContacts.Where(x => x.IsChecked).Count() > 0)                    {<table class="table table-striped"><thead><tr><th>Naam</th><th>Functie</th><th>E-mailadres</th><th>Organisatie</th><th></th></tr></thead><tbody>                                @foreach (var contact in _debtorContacts.Where(x => x.IsChecked))                                {<tr><td>@(contact.Name)</td><td>@(contact.Position)</td><td>@(contact.Email)</td><td>@(contact.Debtor.Name)</td><td><svg @onclick="() => DebtorContactClicked(contact)" style="cursor:pointer;" xmlns="http://www.w3.org/2000/svg" width="1.5em" height="1.5em" viewBox="0 0 16 16"><path fill="red" fill-rule="evenodd" d="M5.75 3V1.5h4.5V3zm-1.5 0V1a1 1 0 0 1 1-1h5.5a1 1 0 0 1 1 1v2h2.5a.75.75 0 0 1 0 1.5h-.365l-.743 9.653A2 2 0 0 1 11.148 16H4.852a2 2 0 0 1-1.994-1.847L2.115 4.5H1.75a.75.75 0 0 1 0-1.5zm-.63 1.5h8.76l-.734 9.538a.5.5 0 0 1-.498.462H4.852a.5.5 0 0 1-.498-.462z" clip-rule="evenodd" /></svg></td></tr>                                }</tbody></table>                    }<br /><MudSelect T="Meeting" Label="Gekoppelde vergaderingen" ToStringFunc="DisplayMeetingValue" MultiSelection="true" @bind-SelectedValues="_selectedMeetings">                        @foreach (var meeting in _existingMeetings)                        {<MudSelectItem T="Meeting" Value="@meeting">                                @(meeting.DateTime.ToLongDateString() +" - " + meeting.Name)</MudSelectItem>                        }</MudSelect><br /><div class="form-group mt-4"><button disabled="@(_disableButtonClicks)" type="submit" class="btn btn-primary btn-rounded mb-3 d-flex align-items-center @((_disableButtonClicks) ? "buttonClicksDisabled" : "")"><iconify-icon class="me-1" icon="material-symbols:save-outline" width="16" height="16"></iconify-icon>                            @((_meeting.Id == 0) ? "Toevoegen" : "Opslaan")</button></div></div><SpColFooter></SpColFooter></div> @* END GENERAL TAB *@</div> @* END TAB CONTENT *@</div> @* END TAB SECTION *@</EditForm>

I have tried countless times to write a working HandleSubmit button. All the child entities must be added/updated/removed when saving a new or existing meeting.

I get a lot of errors:

Cannot insert explicit value for identity column in table 'BoardMembers' when IDENTITY_INSERT is set to OFF.

Cannot insert explicit value for identity column in table 'Debtors' when IDENTITY_INSERT is set to OFF.

Cannot insert explicit value for identity column in table 'Meetings' when IDENTITY_INSERT is set to OFF.

I've had code that did not throw an error when saving. But the child entities were not saved.

My question

What is the correct way to:

  • Collect all the existing DebtorContacts, BoardMembers and Meetings to this page
  • Save this Meeting then adding or updating

This is the current HandleSubmit method I have now. This Method saves existing Meetings with all child entities just fine. But when I add a new one with child entities, the meeting is saved without the child entities:

private async Task HandleSubmit(){    if (_disableButtonClicks)          return;    try    {        _disableButtonClicks = true;        _meeting.DateTime = DateTime.Parse(_meeting.DateTime.ToShortDateString() +" " + Time.ToShortTimeString());        using (var context = _dbContext.CreateDbContext())        {            if (_meeting.Id == 0)            {                _meeting.CreatedOn = DateTime.Now;                _meeting.CreatedBy = await _currentUserService.GetCurrentUserIdAsync();                _meeting.ModifiedOn = DateTime.Now;                _meeting.ModifiedBy = await _currentUserService.GetCurrentUserIdAsync();                if (_meeting.IsBoardMeeting)                {                    _meeting.AgendaItems = await CreateMeetingAgendaItemsAsync();                }                context.Meetings.Add(_meeting);            }            else            {                var existingMeeting = await context.Meetings                    .Include(m => m.DebtorAttendees)                    .Include(m => m.BoardMembers)                    .Include(m => m.ChildMeetings)                    .FirstOrDefaultAsync(m => m.Id == _meeting.Id);                if (existingMeeting == null)                {                    Snackbar.Add("Meeting not found.", Severity.Error);                    return;                }                // Update board members                foreach (var member in _boardMembers)                {                    var existingMember = existingMeeting.BoardMembers.FirstOrDefault(x => x.Id == member.Id);                    if (member.IsChecked)                    {                        if (existingMember == null)                        {                            existingMeeting.BoardMembers.Add(member);                        }                    }                    else                    {                        if (existingMember != null)                        {                            existingMeeting.BoardMembers.Remove(existingMember);                        }                    }                }                // Update debtor attendees                foreach (var attendee in _debtorContacts)                {                    var existingAttendee = existingMeeting.DebtorAttendees.FirstOrDefault(x => x.Id == attendee.Id);                    if (attendee.IsChecked)                    {                        if (existingAttendee == null)                        {                            existingMeeting.DebtorAttendees.Add(attendee);                        }                    }                    else                    {                        if (existingAttendee != null)                        {                            existingMeeting.DebtorAttendees.Remove(existingAttendee);                        }                    }                }                // Update child meetings                existingMeeting.ChildMeetings.Clear();                if (_selectedMeetings != null)                {                    foreach (var meeting in _selectedMeetings)                    {                        var existingChild = await context.Meetings.FindAsync(meeting.Id);                        if (existingChild != null)                        {                            existingMeeting.ChildMeetings.Add(existingChild);                        }                    }                }                existingMeeting.ModifiedOn = DateTime.Now;                existingMeeting.ModifiedBy = await _currentUserService.GetCurrentUserIdAsync();                context.Meetings.Update(existingMeeting);            }            var result = await context.SaveChangesAsync();            if (result > 0)            {                Snackbar.Add(_meeting.Id == 0 ? "New meeting added successfully." : "Meeting updated successfully.", Severity.Success);                await _hub.SendAsync("CUD", "meeting", _meeting.Id);                await PageHistoryService.GoBackOnePage();            }            else            {                Snackbar.Add("Something went wrong! Please try again later...", Severity.Error);            }        }    }    catch (Exception ex)    {        // Log the exception and show a user-friendly message        Console.WriteLine($"Error during submit: {ex.Message}");        Snackbar.Add("Something went wrong! Please try again later...", Severity.Error);    }    finally    {        _disableButtonClicks = false;    }}private async Task<List<MeetingAgendaItem>> CreateMeetingAgendaItemsAsync(){    var currentUserId = await _currentUserService.GetCurrentUserIdAsync();    var now = DateTime.Now;    return _agendaItems.Select(item => new MeetingAgendaItem    {        Title = item.Description,        DefaultParent = item.DefaultParent,        CreatedOn = now,        CreatedBy = currentUserId,        ModifiedOn = now,        ModifiedBy = currentUserId    }).ToList();}

This is my method that collects the existing items from the database. Is this the correct way? Do I need to use AsNoTracking() or not?

private async Task RefreshData(bool? showMessage = true){    Context = _dbContext.CreateDbContext();    _boardMembers = await Context.BoardMembers                                 .AsNoTracking()                                 .Where(x => x.Deleted == false)                                 .ToListAsync();    _existingMeetings = await Context.Meetings                                     .AsNoTracking()                                     .Where(x => x.Deleted == false && x.MeetingClosed == true && x.MinutesApproved == null)                                     .ToListAsync();    _debtorContacts = await Context.DebtorContacts                                   .AsNoTracking()                                   .Include(x => x.Debtor)                                   .AsNoTracking()                                   .AsNoTrackingWithIdentityResolution()                                   .Where(x => x.Deleted == false)                                   .ToListAsync();    _agendaItems = await Context.StandardMeetingAgendaItems                                .AsNoTracking()                                .OrderBy(x => x.Index)                                .Where(x => x.Deleted == false)                                .ToListAsync();}

Viewing all articles
Browse latest Browse all 4839

Trending Articles



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