locked
Update problem RRS feed

  • Question

  • User-1104215994 posted

    Hi,

    I am trying to update the table. But it does not. How come, I don't understand. There is no error either.

    ...
    var gameBankResult =
                        await _unitOfWork.GameBankRepository.GetGamesAsync(g =>
                            g.productCode == requestDto.productCode && g.referenceId == Guid.Empty); --> returns 1 result
    
                    //If we have exact number of games in our database, mark them!
                    if (gameBankResult.Count() != 0 && gameBankResult.Count() >= requestDto.quantity)
                    {
                        for (var index = 0; index < requestDto.quantity; index++)
                        {
                            var item = gameBankResult[index];
                            item.referenceId = gameRequest.referenceId;
                            item.requestDateTime = DateTime.Now;
                            item.responseDateTime = DateTime.Now;
                            _unitOfWork.GameBankRepository.Update(item);
                            await _unitOfWork.SaveAsync(); ---> does not update the table
                        }
    
                        //Query GameBank database
                        var gameBankConfirmResult =
                            await _unitOfWork.GameBankRepository.GetGamesAsync(g =>
                                g.referenceId == gameRequest.referenceId); ---> returns no result
                    ...

    Generic Repo:

    public virtual void Update(TEntity entityToUpdate)
            {
                dbSet.Attach(entityToUpdate);
                context.Entry(entityToUpdate).State = EntityState.Modified;
            }

    Unit of work:

    public async Task SaveAsync()
            {
                await _context.SaveChangesAsync();
                
            }

    Wednesday, July 24, 2019 6:52 PM

Answers

  • User-1104215994 posted

    I keep the transaction but changed my business logic. Now everything works just I want.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Sunday, July 28, 2019 6:16 PM

All replies

  • User1724605321 posted

    Hi cenk1536,

    Please provide the entire codes . for example ,Unit of Work Class to help reproduce .

    You can also refer to below code sample for Implementing the Repository and Unit of Work Patterns in an ASP.NET MVC Application :

    https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application 

    Best Regards,

    Nan Yu

    Thursday, July 25, 2019 2:05 AM
  • User-1104215994 posted

    It is due to Transaction scope. If I don't use Transaction scope it is updated immediately but this time how can I rollback if one of the insert/updates fails.

    private async Task<HttpResponseMessage> CallGame(RequestDto requestDto)
            {
                
                HttpResponseMessage response = null;
                using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
                {
                    //Transform DTO into GameRequest for calling Game Initiate
                    var config = new MapperConfiguration(cfg =>
                    {
                        cfg.CreateMap<RequestDto, GameRequest>();
                        cfg.CreateMap<GameRequest, GameConfirmRequest>();
                        cfg.CreateMap<GameBank, GameConfirmResponse>();
                        cfg.CreateMap<GameBankPin, Coupon>();
                        cfg.CreateMap<GameRequest, GameRequestDto>();
                    });
                    var iMapper = config.CreateMapper();
                    var gameRequest = iMapper.Map<RequestDto, GameRequest>(requestDto);
                    //Unique reference ID
                    gameRequest.referenceId = Guid.NewGuid();
    
                    var gameRequestDto = iMapper.Map<GameRequest, GameRequestDto>(gameRequest);
                    //Create signature
                    gameRequest = Utilities.CreateSignature(gameRequestDto, RequestType.Initiate);
    
                    //Add initiation request into database
                    _unitOfWork.GameRepository.Insert(gameRequest);
    
                    //Query GameBank database
                    var gameBankResult =
                        await _unitOfWork.GameBankRepository.GetGamesAsync(g =>
                            g.productCode == requestDto.productCode && g.referenceId == Guid.Empty);
    
                    //If we have exact number of games in our database, mark them!
                    if (gameBankResult.Count() != 0 && gameBankResult.Count() >= requestDto.quantity)
                    {
                        for (var index = 0; index < requestDto.quantity; index++)
                        {
                            var item = gameBankResult[index];
                            item.referenceId = gameRequest.referenceId;
                            item.requestDateTime = DateTime.Now;
                            item.responseDateTime = DateTime.Now;
                            _unitOfWork.GameBankRepository.Update(item);
                            await _unitOfWork.SaveAsync();
                        }
    
                        //Query GameBank database
                        var gameBankConfirmResult =
                            await _unitOfWork.GameBankRepository.GetGamesAsync(g =>
                                g.referenceId == gameRequest.referenceId);
                        if (gameBankConfirmResult != null)
                        {
                            if (gameBankConfirmResult.Count == 1)
                            {
                                var gameBankConfirmResponse = iMapper.Map<IList<GameBank>, IList<GameConfirmResponse>>(gameBankConfirmResult);
                                gameBankConfirmResponse[0].purchaseStatusDate = DateTime.Now;
                                //Add confirm response into database
                                _unitOfWork.GameConfirmResponseRepository.Insert(gameBankConfirmResponse[0]);
                                var resultResponse = JsonConvert.SerializeObject(
                                    gameBankConfirmResponse[0],Formatting.Indented,
                                new JsonSerializerSettings()
                                {
                                    ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
                                });
                                response = new HttpResponseMessage
                                {
                                    StatusCode = System.Net.HttpStatusCode.OK,
                                    Content = new StringContent(
                                        resultResponse, System.Text.Encoding.UTF8,
                                        "application/json"),
                                };
                            }
                            else if(gameBankConfirmResult.Count > 1)
                            {
                                var gameResult = new GameConfirmResponse
                                {
                                    coupons = new List<Coupon>()
                                };
                                var price = 0.0;
                                var quantity = 0;
    
                                foreach (var item in gameBankConfirmResult)
                                {
                                    price = price + item.unitPrice;
                                    quantity = quantity + 1;
                                    foreach (var coupons in item.coupons)
                                    {
                                        var gameCouponResult = new Coupon()
                                        {
                                            expiryDate = coupons.expiryDate,
                                            Pin = coupons.Pin,
                                            Serial = coupons.Serial
                                        };
                                        //Add coupon values
                                        gameResult.coupons.Add(gameCouponResult);
                                    }
    
                                }
    
                                //Set summed/counted values
                                gameResult.referenceId = gameBankConfirmResult[0].referenceId;
                                gameResult.productCode = gameBankConfirmResult[0].productCode;
                                gameResult.quantity = quantity;
                                gameResult.currency = gameBankConfirmResult[0].currency;
                                gameResult.unitPrice = gameBankConfirmResult[0].unitPrice;
                                gameResult.totalPrice = price;
                                gameResult.productDescription = gameBankConfirmResult[0].productDescription;
                                gameResult.totalPayablePrice = price;
    
                                //var gameBankConfirmResponse = iMapper.Map<GameBank, GameConfirmResponse>(gameResult);
                                //Add confirm response into database
                                _unitOfWork.GameConfirmResponseRepository.Insert(gameResult);
                                var resultResponse = JsonConvert.SerializeObject(
                                    gameResult, Formatting.Indented,
                                    new JsonSerializerSettings()
                                    {
                                        ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
                                    });
                                response = new HttpResponseMessage
                                {
                                    StatusCode = System.Net.HttpStatusCode.OK,
                                    Content = new StringContent(
                                        resultResponse, System.Text.Encoding.UTF8,
                                        "application/json"),
                                };
                            }
                        }
                    }
    
                    await _unitOfWork.SaveAsync();
    
                    scope.Complete();
                }
    
                return response;
            }

    Thursday, July 25, 2019 5:37 AM
  • User753101303 posted

    how can I rollback if one of the insert/updates fails.

    As I tried to tell earlier this is already what EF 6 and EF Core does out of the box for SaveAsync: https://docs.microsoft.com/en-us/ef/core/saving/transactions

    It seems you added your own transaction scope which may "hide" an actual problem you had previously. Instead I would drop using TransactionScope and would fix the actual issue.

    Thursday, July 25, 2019 11:44 AM
  • User-1104215994 posted

    How can I use BeginTransaction with <g class="gr_ gr_4 gr-alert gr_gramm gr_inline_cards gr_run_anim Grammar only-ins doubleReplace replaceWithoutSep" id="4" data-gr-id="4">unit</g> of work? Any sample you can show?

    using (var transaction = context.Database.BeginTransaction())
        {
            try
            {
                context.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/dotnet" });
                context.SaveChanges();
    
                context.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/visualstudio" });
                context.SaveChanges();
    
                var blogs = context.Blogs
                    .OrderBy(b => b.Url)
                    .ToList();
    
                // Commit transaction if all commands succeed, transaction will auto-rollback
                // when disposed if either commands fails
                transaction.Commit();
            }
            catch (Exception)
            {
                // TODO: Handle failure
            }
        }

    Thursday, July 25, 2019 12:01 PM
  • User753101303 posted

    It should be just;

    context.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/dotnet" });
    context.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/visualstudio" });
    context.SaveChanges();

    ie do all changes to the "repository" and then call SaveChanges once.

    When  SaveChanges is called, EF inspect all objects attached to the context (directly or even indirectly ie an Order related to OrderDetails for example), and figure out how to update all that in the correct order within a single transaction.

    Add for example a 3rd row that would exceed the allowed length for this blog entry or maybe a value that already exists if you have a unique constraint and you'll see that if SaveChanges fails nothing at all is added to the db.

    Similarly in the previous code you are calling SaveChanges from within a loop. In most cases you should do all changes and then call this one time at the end to save all changes (or no change at all).

    Thursday, July 25, 2019 12:34 PM
  • User-474980206 posted

    just rollback in the error handler:

    using (var transaction = context.Database.BeginTransaction())
        {
            try
            {
                context.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/dotnet" });
                context.SaveChanges();
    
                context.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/visualstudio" });
                context.SaveChanges();
    
                var blogs = context.Blogs
                    .OrderBy(b => b.Url)
                    .ToList();
    
                // Commit transaction if all commands succeed, transaction will auto-rollback
                // when disposed if either commands fails
                transaction.Commit();
            }
            catch (Exception)
            {
                transaction.RollBack();
            }
        }

    but as suggested if you use an implicit transaction, it will be faster, as its done in a single batch, rather than as separate batches.

    Thursday, July 25, 2019 5:10 PM
  • User-1104215994 posted

    I keep the transaction but changed my business logic. Now everything works just I want.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Sunday, July 28, 2019 6:16 PM