Base solution for your next web application
Open Closed

How to circumvent Abp/Zero database transactions? #7635


User avatar
0
TimMackey created

Is there any interface available in Abp/Zero (Angular/Core) that will allow context.SaveChanges(); to be immediately written to the database, and NOT wait until the thread is exited?

Using UnitOfWork is not an option, as that introduces its own overhead.

I'm seeking a high-performance solution to write one row at a time to my Apb/Zero db.

Markdown is supported
Copy & paste or drag & drop images (max 30 MB per image)

10 Answer(s)
  • User Avatar
    0
    maliming created
    Support Team

    You can disable the unit of work.

    [UnitOfWork(IsDisabled = true)]
    public virtual void RemoveFriendship(RemoveFriendshipInput input)
    {
        _friendshipRepository.Delete(input.Id);
    }
    
    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    TimMackey created

    Where does this function reside? How and when is it invoked? The Abp documentation page does not answer these questions.

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    maliming created
    Support Team

    @timmackey see https://aspnetboilerplate.com/Pages/Documents/Unit-Of-Work#unit-of-work-in-detail

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    TimMackey created

    I implemented the suggested code changes. Records are not committed to the physical db and performance is 3X SLOWER than the same code in ASP.NET.

    Is there anything I might have missed that would be preventing commit or result in degraded performance?

    using System;
    using System.Collections.Generic;
    using System.Linq;
    
    #if NETFRAMEWORK
    using DataModelLibrary.Exams;
    using DbContext = DataModelLibrary.Exams.DbContext_Exam;
    #endif
    
    #if NETCOREAPP   // https://docs.microsoft.com/en-us/dotnet/standard/frameworks
    using Abp.Domain.Uow;
    using Abp.EntityFrameworkCore;
    using System.Transactions;
    
    using ngTTM.TtmDataModel;
    using DbContext = ngTTM.EntityFrameworkCore.ngTTMDbContext;
    #endif
    
    // for clarity, all NETFRAMEWORK-specific code has been removed
    namespace JobsLibrary
    {
        public class CreateExamsDemo
        {
            //-----------------------------------------------------------------------------------------
            private readonly IDbContextProvider<DbContext> _dbContextProvider;
            //-----------------------------------------------------------------------------------------
            public CreateExamsDemo(IDbContextProvider<DbContext> dbContextProvider)
            {
                _dbContextProvider = dbContextProvider;
            }
            //-----------------------------------------------------------------------------------------
            [UnitOfWork(IsDisabled = true)]
            // [UnitOfWork(isTransactional: false)]
            public bool Create(string guid, string rootFolder)
            {
                DateTime _StartTime = DateTime.Now;
                try
                {
                    using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Suppress))
                    {
                        DbContext context = _dbContextProvider.GetDbContext();
                        {
                            Exam exam = context.Exams.First(x => x.Guid == guid);
    
                            // not shown are calls to other functions accessing many db tables
                            // the code fragment below illustrates the concept
    
                            List<ExamQuestion> examQuestionsList = new List<ExamQuestion>();
                            // add multiple ExamQuestion to list
                            context.ExamQuestions.AddRange(examQuestionsList);
                            // acquire table "id" values used in next processing steps (not shown)
                            context.SaveChanges();
    
                            // typical execution time in NETFRAMEWORK is approx. 4 minutes
                            // typical execution time in NETCOREAPP is approx. 16 minutes
                            exam.CreateDuration = (float)(DateTime.Now - _StartTime).TotalSeconds;
                            context.SaveChanges();
                            return true;
                        }
                    }
                }
                catch (Exception ex)
                {
                    // Exception handler
                    return false;
                }
                //-----------------------------------------------------------------------------------------
            }
        }
    }
    
    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @timmackey

    If the item count in examQuestionsList is too much, you might try to use raw SQL to insert records. Entity Framework is not good with batch inserts.

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    TimMackey created

    @ismcagdas,

    I'm not confident that converting my app from EF to SQL would be effective. it's a lot of code that would need to be changed, and I'm concerned that SQL updates will not effect until transaction/thread completion after all the changes.

    I'm using EF in ASP.NET Framework 4.5.2 in my original app; excellent performance and the db is updated upon context.SaveChanges(). EF in Zero/Core however has slower performance and the db is NOT updated upon context.SaveChanges(); the db is updated upon transaction/thread completion.

    I think the mystery now is why non-transactional unit of work attributes (as recommended by @maliming) are not working.

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    maliming created
    Support Team

    I think the mystery now is why non-transactional unit of work attributes (as recommended by @maliming) are not working.

    Note that if a unit of work method calls this RemoveFriendship method, disabling this method is ignored, and it will use the same unit of work with the caller method.

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    BobIngham created

    @timmackey, implement an sql repository in the entity framework project and call the methods directly from your app service. All of my grid information is read in such a way, sometimes it is simpler and more performant to work directly with the database without the Zero overhead.

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    ismcagdas created
    Support Team

    @timmackey

    I think the mystery now is why non-transactional unit of work attributes (as recommended by @maliming) are not working.

    Probably becasue your method is not virtual

    public bool Create(

    If you convert to to virtual, probably it will work:

    public virtual bool Create(

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    TimMackey created

    Converting to virtual solved the issue. See #7550 for complete solution.

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)