Readdy Write  
0,00 €
Your View Money
Views: Count
Self 20% 0
Your Content 60% 0

Users by Links 0
u1*(Content+Views) 10% 0
Follow-Follower 0
s2*(Income) 5% 0

Count
Followers 0
Login Register as User

Resolved: fail: Microsoft.EntityFrameworkCore.Update [10000] An exception occurred in the database while saving changes

17.05.2018 (👁8790)


 

 

Remedy of the error

//*fail: Microsoft.EntityFrameworkCore.Update[10000]

//*An exception occurred in the database while saving changes for context type 'Readdy.Data.ApplicationDbContext'.

//*System.InvalidOperationException: A second operation started on this context before a previous operation completed. Any instance members are not guaranteed to be thread safe.

 

Problem:

If you write simple data on a SQL Server that needs a quick transfer without much intermediate testing, then working with the Entity Framework sometimes causes problems.

In an Asp.Net web server environment with many concurrent client accesses, the same data sets can be quickly described by others while reading.

 

The problem is that Entitiy Framework briefly loads the data as an ADO record from SQL Server to the IIS web server. In the meantime, there may be changes, which are usually checked with EF.

Testing is implemented with EF tracking.

 

For simple read operations, data tracking can be turned off and the data executed directly with SQL Execute commands.

 

 

Easy Reading of Data with AsNoTracking ()

Example in Asp.Net Core 2 with EF and Linq

//< with dbContext >

User_SumModel sumInfo = Database.EF_Model.dbContext.tbl_User_Sums.AsNoTracking().FirstOrDefault(u => u.IDUser == IDUser);

//</ with dbContext >

 

 

Direct writing to SQL Server can be done with ExecuteSqlCommand (sql)

Database.EF_Model.dbContext.Database.ExecuteSqlCommand(sSQL);

 

My example code

Here it is checked whether an info record exists, if not, then a new record is created, otherwise a counter is incremented in the info record.

The reading of the data record takes place with EF.AsNoTracking () readonly.

The write processes take place directly on the SQL Server.

    public static void increase_User_SumViews_Self_byIDUser(long IDUser)

    {

        //------------< increase_User_SumViews_Self(User) >------------

        try

        {

            //*get User Summary Table

            //< with dbContext >

            User_SumModel sumInfo = Database.EF_Model.dbContext.tbl_User_Sums.AsNoTracking().FirstOrDefault(u => u.IDUser == IDUser);

            //</ with dbContext >

 

            //--< Increment SumCounter >--

            string sSQL;

            if (sumInfo == null)

            {

                sSQL = "INSERT INTO [dbo].[tbl_User_Sums]";

                sSQL += Environment.NewLine + "([IDUser],[dtStart],[dtEnd],[SumViews_Self])";

                sSQL += Environment.NewLine + "VALUES(123, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 1)";

            }

            else

            {

                sSQL = "UPDATE[dbo].[tbl_User_Sums]  SET [SumViews_Self] = ISNULL([SumViews_Self], 0)+1  ,[dtEnd]=CURRENT_TIMESTAMP   WHERE [IDUser]=" + IDUser;               

            }

            Database.EF_Model.dbContext.Database.ExecuteSqlCommand(sSQL);

            //--</ Increment SumCounter >--

 

        }

        finally

        { }

        //------------</ increase_User_SumViews_Self(User) >------------

    }

 

 

The debugger shows that the update command does not increase the previously read counter value in the EF buffer.

The increase in the value on the SQL server itself has already taken place. The value is not used and therefore does not need to be tracked.

 

 

 

Reference:

Former Entity Framework Code, which already worked, but was optimized as described above

//*fail: Microsoft.EntityFrameworkCore.Update[10000]

    //*An exception occurred in the database while saving changes for context type 'Readdy.Data.ApplicationDbContext'.

    //*System.InvalidOperationException: A second operation started on this context before a previous operation completed. Any instance members are not guaranteed to be thread safe.

    //public static await Task increase_User_SumViews_Self_byIDUser(long IDUser)

    public static void increase_User_SumViews_Self_byIDUser(long IDUser)

    {

        //------------< increase_User_SumViews_Self(User) >------------

        try

        {

            //*get User Summary Table

            User_SumModel summary = new User_SumModel();

 

            //< with dbContext >

            //summary = await Database.EF_Model.dbContext.tbl_User_Sums.FirstOrDefaultAsync(u => u.IDUser == IDUser);           

            summary = Database.EF_Model.dbContext.tbl_User_Sums.FirstOrDefault(u => u.IDUser == IDUser);

            //</ with dbContext >

 

            //--< Increment SumCounter >--

            if (summary == null)

            {

                summary = new User_SumModel();

                summary.SumViews_Self = 1;

                summary.IDUser = IDUser;

                summary.dtStart = DateTime.Now;

                summary.dtEnd = DateTime.Now;

                Database.EF_Model.dbContext.tbl_User_Sums.Add(summary);                

            }

            else

            {

                summary.SumViews_Self += 1;

                summary.dtEnd = DateTime.Now;

            }

 

            //await Database.EF_Model.dbContext.SaveChangesAsync(true);

            Database.EF_Model.dbContext.SaveChanges(true);

            //--</ Increment SumCounter >--

 

        }

        finally

        {

 

        }

 

 

 

        //------------</ increase_User_SumViews_Self(User) >------------

    }