none
MultiTasking with EntityFramework RRS feed

  • Question

  • Hi All

    I'm developing a MVC application with Entity Framework 5.0 with .net Framework 4.5.

    Everything was running fine until I started using Tasks in my project.

    I need to update a column in  a table, and as there will be some thousands of records(probably more than a lakh), I used multitasking feature in order to improve the performance and this is where I am stuck up with.

    private void UpdatePage(int keyID)
            {            
                int batchSize = 1000;
                int batch = 0;
                int pageCount = GetTotalNumberOfPages();
                var tasks = new List<Task>();            
                do
                {
                   if (tasks.Count >= 3)
                {                                
                      var completed = Task.WaitAny(tasks.ToArray());              
                    tasks.RemoveAt(completed);
                }
                    var batchNumber = batch;
                    tasks.Add(Task.Factory.StartNew(() => SubmitBatchOfPages(batchSize, batchNumber, keyID)));                
                    batch++;
                } while ((batch * batchSize) < pageCount);           
                Task.WaitAll(tasks.ToArray());
            }
    
    private void SubmitBatchOfPages(int batchSize, int batch, int keyID)
            {
                var context = new SampleContext();
                context.Configuration.AutoDetectChangesEnabled = false;
                context.Configuration.ValidateOnSaveEnabled = false;                       
    
                var pagesQuery = context.Pages
                    .Where(p => p.KeyID == keyID)
                    .OrderBy(p => p.PageID)
                    .Skip(batch * batchSize)
                    .Take(batchSize).AsNoTracking();
    
                var pages = pagesQuery.ToList();    
    
                    foreach (var page in pages)
                    {
                        
                            page.UpdatedDate = DateTime.Now;                    
                        context.Pages.Attach(page);
                        context.Entry<Page>(page).Property(p => p.UpdatedDate).IsModified = true;
                    }
                    context.Configuration.AutoDetectChangesEnabled = true;
                    context.Configuration.ValidateOnSaveEnabled = true;
    context.SaveChanges();                
            }

    When I run this code, the site is never up nor any exception is thrown. when I tried to debug the code, it hangs at the line 

    Task.WaitAll(tasks.ToArray());

    However long you run the code, it will be at this line executing.

    My Questions:

    1) What is wrong in my code? when I ran the code without Tasks, it was successfull.

    2) Does EntityFramework support Tasks?

    Thanks in advance.


    Murali Mahendra Banala

    Wednesday, November 27, 2013 10:18 AM

All replies

  • Hello,

    With your codes, I made a test, however it worked fine. Here is my codes:

    internal void Execute()
    
            {
    
                int batchSize = 1000;
    
                int batch = 0;
    
                int pageCount = 500000;
    
                var tasks = new List<Task>();
    
                int i = 1;
    
                do
    
                {
    
                    int orderID = i++;
    
                    if (tasks.Count >= 3)
    
                    {
    
                        var completed = Task.WaitAny(tasks.ToArray());
    
                        tasks.RemoveAt(completed);
    
                    }
    
                    var batchNumber = batch;
    
                    tasks.Add(Task.Factory.StartNew(() => SubmitBatchOfPages(batchSize, batchNumber, orderID)));
    
                    batch++;
    
                } while ((batch * batchSize) < pageCount);
    
                Task.WaitAll(tasks.ToArray());
    
    
            }
    
    
            private void SubmitBatchOfPages(int batchSize, int batch, int keyID)
    
            {
    
                DataBaseFirstDBEntities context = new DataBaseFirstDBEntities();
    
                context.Configuration.AutoDetectChangesEnabled = false;
    
                context.Configuration.ValidateOnSaveEnabled = false;
    
    
                var pagesQuery = context.Orders.Where(order => order.OrderID == keyID);
    
    
                var pages = pagesQuery.ToList();
    
    
                foreach (var page in pages)
    
                {
    
    
                    page.OrderCode = "000000001";
    
                    context.Orders.Attach(page);
    
                    context.Entry<Order>(page).Property(p => p.OrderCode).IsModified = true;
    
                }
    
                context.Configuration.AutoDetectChangesEnabled = true;
    
                context.Configuration.ValidateOnSaveEnabled = true;
    
                context.SaveChanges();
    
                Console.WriteLine(keyID);
    
                Console.WriteLine(DateTime.Now);
    
            }
    

    Running result:

    In the SubmitBatchOfPages() method, I add the two line codes below to see whether the program is in working:

    Console.WriteLine(keyID);
    
    Console.WriteLine(DateTime.Now);
    

    You can have a try.

    I used the Entity Framework 5 and .Net 4.5, too.

    Regards.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Thursday, November 28, 2013 6:42 AM
    Moderator
  • Thank you Fred.

    I suppose you executed the same code without any changes. But still I'm unable to run that in my system. Is is still hanging on the line 

    Task.WaitAll(tasks.ToArray());

    To mention, I'm following Code First pattern with Entity Framework and I'm running this method in migrations.

    I have uploaded my sample project at "http://sdrv.ms/Iis5OB". 

    Can you please download my sample app and test it? [the sample contains no UI, I'm just running the migration to check whether it will be executed. You can find this cod in the MIgrations folder.]


    Murali Mahendra Banala


    Thursday, November 28, 2013 10:25 AM
  • Hi,

    I downloaded it. However I did not find the codes in the MIgrations folder...

    unknown class:

    public partial class unknown : DbMigration
    
        {
    
            public override void Up()
    
            {
    
                CreateTable(
    
                    "dbo.Page",
    
                    c => new
    
                        {
    
                            PageID = c.Guid(nullable: false),
    
                            DocumentID = c.Int(nullable: false),
    
                            StorageIdentifier = c.String(maxLength: 500, unicode: false),
    
                            FileExtension = c.String(maxLength: 5, unicode: false),
    
                            PageNum = c.Int(nullable: false),
    
                            IsDeleted = c.Boolean(nullable: false),
    
                            KeyID = c.Int(nullable: false),
    
                            EncryptedIV = c.Binary(),
    
                        })
    
                    .PrimaryKey(t => t.PageID);
    
                
    
            }
    
            
    
            public override void Down()
    
            {
    
                DropTable("dbo.Page");
    
            }
    
        }
    

    Configuration Class:

    internal sealed class Configuration : DbMigrationsConfiguration<Sample.Data.SampleContext>
    
        {
    
            private readonly IEnumerable<string> _pendingMigrations;
    
            public Configuration()
    
            {
    
                AutomaticMigrationsEnabled = false;
    
                AutomaticMigrationDataLossAllowed = false;
    
                var dbMigrator = new DbMigrator(this);
    
                _pendingMigrations = dbMigrator.GetPendingMigrations();
    
            }
    
            protected override void Seed(Sample.Data.SampleContext context)
    
            {
    
                var dbMigrator = new DbMigrator(this);
    
                var pendingMigrations = dbMigrator.GetDatabaseMigrations().Count();
    
                new BaseData(context, _pendingMigrations);
    
            }
    
        }
    

    UnProtectPageIV Class:

    public partial class UnProtectPageIV : DbMigration
    
        {
    
            public override void Up()
    
            {
    
            }
    
            
    
            public override void Down()
    
            {
    
            }
    
        }
    


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Friday, November 29, 2013 6:51 AM
    Moderator
  • Sorry Fred, 

    I meant this migration is called from Configuration class inside the Seed method.

    If you navigate to BaseData class, you can find the code over there. 

    One more update on this, 

    Trying to understand the cause of the problem, I have tried to execute the code from outside the migration and it ran successfully. But when the same code is running through a migration, it is hanging.

    Any idea for this behavior. 


    Murali Mahendra Banala


    Friday, November 29, 2013 7:09 AM