Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I kick off an entity stored procedure in EF6 async and not wait for a return?

I'd like to just punt a call over to the SQL Server and not wait for a return. I have an imported Entity Function from a Stored Procedure that I'd like to call asynchronously this way in Entity Framework 6.0.0-rc1. Is this possible? What's the syntax?

Entity Function: RecalculateBudgetNumbers(int id)
like image 411
dirq Avatar asked Oct 08 '13 14:10

dirq


2 Answers

Start a new Task that creates a fresh data context and invokes that function. Just don't wait/await that task. Let it run by itself to completion.

Make sure to log errors. Don't swallow exceptions because they might be bugs you want to know about.

In an ASP.NET setting, be aware that the worker process can recycle at any time at all, so your background work can suddenly disappear (or be cancelled).

like image 152
usr Avatar answered Sep 19 '22 01:09

usr


Ahh. I was in Entity Framework land too long. Thanks for the tips. Here's what worked for me. Do you see any problems with this?

    /// <summary>
    /// kicks off the LONG RUNNING calculations on a budget to regenerate all pre-cooked numbers.
    /// </summary>
    /// <param name="budgetId">Budget Id</param>
    public async System.Threading.Tasks.Task RecalculateBudgetNumbersAsync(int budgetId)
    {
        await System.Threading.Tasks.Task.Factory.StartNew(() => RecalculateBudgetNumbers(budgetId));
    }

    public static void RecalculateBudgetNumbers(int budgetId)
    {
        //this is static so we don't use the unit of work..
        using (BMTContext ctx = new BMTContext())
        {
            ctx.UpdateLifeOfBudgetNumbers(budgetId);                
            ctx.UpdateIntervalNumbers(budgetId);                
            ctx.UpdateIntervalActivityNumbers(budgetId);
            ctx.UpdateLifeOfBudgetActivityNumbers(budgetId);
        }
    }

And my test (I'm in Visual Studio 2012 so I can do an async test).

    [TestMethod]
    public async System.Threading.Tasks.Task RecalculateBudgetNumbersAsyncTest()
    {
        System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
        timer.Start();
        await repo.RecalculateBudgetNumbersAsync(budgetId);

        System.Console.WriteLine("RecalculateBudgetNumbersAsyncTest milliseconds: " + timer.ElapsedMilliseconds.ToString());
    }

After suggestions from Matt Smith and Usr, I changed RecalculateBudgetNumbersAsync to this. I hope this is what they meant:

    public void RecalculateBudgetNumbersAsync(int budgetId)
    {
        System.Threading.Tasks.Task.Factory.StartNew(() => RecalculateBudgetNumbers(budgetId));
    }
like image 37
dirq Avatar answered Sep 20 '22 01:09

dirq