How can I run this entity framework sample faster

前端 未结 2 1399
生来不讨喜
生来不讨喜 2021-01-06 16:50

I have this code for adding about 1500 record to database:

async void button7_Click(object sender, EventArgs e)
{
    var task = await Task.Run(() =>
             


        
相关标签:
2条回答
  • 2021-01-06 17:22

    Parallel processing won't be of big help here, because your loop by itself takes no time at all. All consumed time goes into two things:

    1. When you add new item to Entity Framework context (and you use EF here as I understand) - it performs some operations on many items in the context (not just the item you added) and it goes slower and slower the more items you added.

    2. Perfoming 1500 database inserts also takes some time.

    The easiest thing to do here is to reduce time taken by point 1 in the list above. You can do it like this:

    async void button7_Click(object sender, EventArgs e)
    {
        var task = await Task.Run(() =>
        {
            Random rnd = new Random();
            var tbls = new List<Tbl>();
            for (int i = 0; i <= 1500; i++)
            {
                tbls.Add(new Tbl()
                {
                    Name = "User" + i + 1,
                    Num = rnd.Next(10, i + 10) / 10
                });
                progress.Report(i * 100 / 1500);
             }
            db.Tbls.AddRange(tbls);
            db.SaveChanges();
            return db.Tbls.Count();
    
        });
    }
    

    By using AddRange and first collecting all items in simple List you will greately reduce time consumed by your code to at least below 1 second.

    Update. If you want to use parallel loop, even if that won't help, you can do it like this:

    int seed = Environment.TickCount;
    var random = new ThreadLocal<Random>(() => new Random(Interlocked.Increment(ref seed)));
    var tbls = new ConcurrentBag<Tbl>();
    Parallel.For(0, 1500, (i) => {
        tbls.Add(new Tbl()
        {
            Name = "User" + i + 1,
            Num = random.Value.Next(10, i + 10) / 10
        });
    });                
    db.Tbls.AddRange(tbls);
    

    Things to note:

    • Random is not thread safe so we use thread local instances (one for each thread inside parallel loop), each one with different seed value.
    • List is not thread safe - we use ConcurrentBag instead.
    0 讨论(0)
  • 2021-01-06 17:24

    If performance is the goal then you should use something other than EF like dapper (same thing StackOverflow.com is using) or raw ADO.Net. Other than that you could improve the Entity Framework performance by disabling change auto detection and validation on save:

    yourDbContext.Configuration.AutoDetectChangesEnabled = false;
    yourDbContext.Configuration.ValidateOnSaveEnabled = false;
    

    You should combine the above code with @Evk advice of using AddRange.

    Another solution that might help speedup your inserts is by using BulkInsert (image taken from here):

    0 讨论(0)
提交回复
热议问题