Skip to content

bug: Error when creating ban in database #70

@ProgrammingByPermutation

Description

Getting errors like the following:

{"date":"2025-03-05T17:28:43.8322621+00:00","level":"ERROR","logger":"Nullinside.Api.TwitchBot.ChatRules.TwitchChatMessageMonitorConsumer","thread":"6","ndc":"(null)","exception":"Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException: The database operation was expected to affect 1 row(s), but actually affected 0 row(s); data may have been modified or deleted since entities were loaded. See https://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.\n   at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ThrowAggregateUpdateConcurrencyExceptionAsync(RelationalDataReader reader, Int32 commandIndex, Int32 expectedRowsAffected, Int32 rowsAffected, CancellationToken cancellationToken)\n   at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ConsumeResultSetAsync(Int32 startCommandIndex, RelationalDataReader reader, CancellationToken cancellationToken)\n   at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ConsumeAsync(RelationalDataReader reader, CancellationToken cancellationToken)\n   at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)\n   at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)\n   at MySql.EntityFrameworkCore.Update.MySQLModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)\n   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)\n   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)\n   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)\n   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IList`1 entriesToSave, CancellationToken cancellationToken)\n   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(StateManager stateManager, Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)\n   at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.<>c__DisplayClass30_0`2.<<ExecuteAsync>b__0>d.MoveNext()\n--- End of stack trace from previous location ---\n   at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteImplementationAsync[TState,TResult](Func`4 operation, Func`4 verifySucceeded, TState state, CancellationToken cancellationToken)\n   at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteImplementationAsync[TState,TResult](Func`4 operation, Func`4 verifySucceeded, TState state, CancellationToken cancellationToken)\n   at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)\n   at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)\n   at Nullinside.Api.TwitchBot.Model.NullinsideContextExtensions.SaveTwitchBans(INullinsideContext db, String channelId, IEnumerable`1 bannedUsers, String reason, CancellationToken stoppingToken) in /src/Nullinside.Api.TwitchBot/Model/NullinsideContextExtensions.cs:line 178\n   at Nullinside.Api.TwitchBot.ChatRules.AChatRule.BanAndLog(String channelId, ITwitchApiProxy botProxy, IEnumerable`1 users, String reason, INullinsideContext db, CancellationToken stoppingToken) in /src/Nullinside.Api.TwitchBot/ChatRules/AChatRule.cs:line 35\n   at Nullinside.Api.TwitchBot.ChatRules.Streamboo.Handle(String channelId, ITwitchApiProxy botProxy, TwitchChatMessage message, INullinsideContext db, CancellationToken stoppingToken) in /src/Nullinside.Api.TwitchBot/ChatRules/Streamboo.cs:line 29\n   at Nullinside.Api.TwitchBot.ChatRules.TwitchChatMessageMonitorConsumer.MainLoop() in /src/Nullinside.Api.TwitchBot/ChatRules/TwitchChatMessageMonitorConsumer.cs:line 159","message":"dark_wing_spacecat: Failed to evaluate rule on tribalgrower(1273391948): Best vi\u011Bw\u0310e\u0329rs \u0333o\u032Bno\u034En streamboo .com ( remove the space )  @6yrwanac"}

There appears to be a pattern for handling concurrency conflicts: https://learn.microsoft.com/en-us/ef/core/saving/concurrency?tabs=data-annotations#resolving-concurrency-conflicts

It's rather cumbersome and implies that boilerplate code should be everywhere we expect to save changes. Which would require more work on our part to ensure we apply this pattern everywhere.

The odd thing about this exception is that there shouldn't be a concurrency issue where because we are inserting brand new records and not "racing" between inserting and updating a single record. Worse case scenario we should end up with duplicate records for the same ban and yet it appears to think we're doing an update?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions