Base solution for your next web application
Open Closed

OPTIMISTIC LOCKING ON DEFAULT REPOSITORY #4551


User avatar
0
ivanosw1 created

Hi, I've the same requirement as this topic [https://forum.aspnetboilerplate.com/viewtopic.php?f=5&t=10262]) but with default repository.

I've a context but I don't need a custom repository and so "override int SaveChanges()" is not raised on my context. How can I catch DbUpdateConcurrencyException on default repository to show a UserFriendlyException?

Thank you.


11 Answer(s)
  • User Avatar
    0
    aaron created
    Support Team

    Override SaveChanges in YourDbContext, as mentioned in that topic.

  • User Avatar
    0
    ivanosw1 created

    Yes I did, but SaveChanges on my context is not raised.

    Always the base method is called. I guess I'm missing something but i don't know what.

  • User Avatar
    0
    aaron created
    Support Team

    Did you override SaveChangesAsync too?

  • User Avatar
    0
    ivanosw1 created

    No. Just did now for all save overrides. The code pass in my context on those methods.. but the exception is not raised here but ahead in code. In logs.txt I can see Database operation expected to affect 1 row(s) but actually affected 0 row(s)

    public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = new CancellationToken())
            {
                try
                {
                    return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
                }
                catch (Exception e)
                {
                    throw;
                }
                
    
            }
    
     public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
            {
                try
                {
                    return base.SaveChangesAsync(cancellationToken);
                }
                catch (Exception e)
                {
                    throw;
                }
              }
    
  • User Avatar
    0
    aaron created
    Support Team
    • What's your expected behaviour?
    • Can you show the full stack trace?
  • User Avatar
    0
    ivanosw1 created

    Expected behaviour: using IRepository<MyEntity> if DbConcurrencyError happens I want to catch the exception and display to user a custom message instead of error.

    Now I have in response to client;

    {
      "result": null,
      "targetUrl": null,
      "success": false,
      "error": {
        "code": 0,
        "message": "An internal error occurred during your request!",
        "details": null,
        "validationErrors": null
      },
      "unAuthorizedRequest": false,
      "__abp": true
    }
    

    and in log

    ERROR 2018-01-23 17:43:24,295 [10   ] Mvc.ExceptionHandling.AbpExceptionFilter - Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
    Abp.Domain.Uow.AbpDbConcurrencyException: Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions. ---> Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException: Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
       at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ThrowAggregateUpdateConcurrencyException(Int32 commandIndex, Int32 expectedRowsAffected, Int32 rowsAffected)
    

    This is my repository

    public class OspiteRepository : IOspiteRepository
        {
            private readonly IRepository<OspiteData> _ospiteDataRepository;
    
            public OspiteRepository(IRepository<OspiteData> ospiteDataRepository)
            {
                _ospiteDataRepository = ospiteDataRepository;
            }
    
                   public void UpdateOspite(Ospite ospite)
            {
                _ospiteDataRepository.Update(ospite.Snapshot);
    
            }
         
        }
    
  • User Avatar
    0
    aaron created
    Support Team

    Then why don't you throw UserFriendlyException?

  • User Avatar
    0
    ivanosw1 created

    Yes I would like to throw UserFriendlyException but where I can catch the DbConcurrencyError ?

  • User Avatar
    0
    aaron created
    Support Team

    Oh, you need to await async methods:

    public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
    {
        try
        {
            return await base.SaveChangesAsync(cancellationToken);
        }
        catch (AbpDbConcurrencyException e)
        {
            throw new UserFriendlyException(e.Message, e);
        }
    }
    
  • User Avatar
    0
    ivanosw1 created

    OK @aaron !!! It works Now I have what I need.

    Thank you so much.

  • User Avatar
    0
    aaron created
    Support Team

    That's great :)