1

I am using LINQ with EntityFramewwork 6 and have most of my methods that I need converted to an asynchronous task.

However, I can't figure out why on these two specific scenarios I am getting these design time compile messages. If somebody can explain to me what I need to do to get the task to be asynchronous, it would be much appreciated.

The first type of synchronous task I want to convert is as follows:

public List<Category> GetProjectsByCategoryID(Int16 categoryid)
        {
            try
            {
                using (YeagerTechEntities DbContext = new YeagerTechEntities())
                {
                    DbContext.Configuration.ProxyCreationEnabled = false;
                    DbContext.Database.Connection.Open();

                    var category = DbContext.Categories.Include("Projects").Where(p => p.CategoryID == categoryid).ToList();

                    return category;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

When I try and change the above method to an asynchronous task (see below), I don't know what asynchronous method to place inbetween the "Include("Projects").(p"

public async Task<List<Category>> GetProjectsByCategoryID(Int16 categoryid)
        {
            try
            {
                using (YeagerTechEntities DbContext = new YeagerTechEntities())
                {
                    DbContext.Configuration.ProxyCreationEnabled = false;
                    DbContext.Database.Connection.Open();

                    var category = await DbContext.Categories.Include("Projects").(p => p.CategoryID == categoryid);

                    return category;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

How can I convert this synchronous method into an asynchronous method?

public List<CustomerEmail> GetCustomerDropDownList()
        {
            try
            {
                using (YeagerTechEntities DbContext = new YeagerTechEntities())
                {
                    DbContext.Configuration.ProxyCreationEnabled = false;
                    DbContext.Database.Connection.Open();

                    var customers = DbContext.Customers.Select(s =>
                        new CustomerEmail()
                        {
                            CustomerID = s.CustomerID,
                            Email = s.Email
                        }).ToList();

                    return customers;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
rgettman
  • 176,041
  • 30
  • 275
  • 357
sagesky36
  • 4,542
  • 19
  • 82
  • 130
  • 1
    Why are you doing `catch (Exception ex){ throw ex;}`? Even if there is logging code before `throw ex;` that you took out to post here you should **never** just call `throw ex;`, you are destroying the stack trace and getting nothing from it. You should either call just `throw;` to preserve the stack trace or `throw new SomeOtherException("Some descriptive text", ex)` so `ex` will be returned as a inner exception. – Scott Chamberlain Nov 05 '13 at 00:08
  • Thanks, I will make that change.... – sagesky36 Nov 05 '13 at 14:17
  • Scott, if I leave it as "throw ex", won't that come back to the calling method, hit the "catch" and handle the ex.Message exception? – sagesky36 Nov 05 '13 at 14:36
  • I don't understand what you mean by that. – Scott Chamberlain Nov 05 '13 at 14:44
  • This method will fall back into a catch statement from the method that called it. Inside that catch, I have a logging mechanism that takes the exception that is thrown back and logs the exception which originally occurred in this method. – sagesky36 Nov 05 '13 at 15:14
  • 1
    Then don't catch at all in this method or use `throw;` instead of `throw ex;`. `ex.StackTrace;` gets replaced with a new stack trace pointing at the location of `throw ex;`. If you use just `throw` or don't catch at all the stack trace points at the actual location the error was raised at. Read [this SO question](http://stackoverflow.com/questions/730250/is-there-a-difference-between-throw-and-throw-ex) for more information. – Scott Chamberlain Nov 05 '13 at 15:22
  • 1
    Got it... Thanks. I'll make that change to the code.... – sagesky36 Nov 05 '13 at 16:00

1 Answers1

2

You were very very close:

public async Task<List<CustomerEmail>> GetCustomerDropDownList()
{
    try
    {
        using (YeagerTechEntities DbContext = new YeagerTechEntities())
        {
            DbContext.Configuration.ProxyCreationEnabled = false;
            DbContext.Database.Connection.Open();

            var customers = await DbContext.Customers.Select(s =>
            new CustomerEmail()
            {
                CustomerID = s.CustomerID,
                Email = s.Email
            }).ToListAsync();

            return customers;
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

Note the ToListAsync(). This will explicitly load and resolve your query, but will do so in an asynchronous fashion.

David L
  • 32,885
  • 8
  • 62
  • 93
  • Thanks.... No design time compile error on that one... However, I did need to put the first line as follows: public async Task> GetCustomerDropDownList() It was missing the "Task" attribute. – sagesky36 Nov 05 '13 at 14:21
  • @sagesky36 I updated my answer to remain consistent. Thanks. – David L Nov 05 '13 at 14:27
  • Typically I don't call MyCollection.ToList() (async or otherwise) as the collection will be evaluated and the collection be immediately placed in memory. How can you return an IEnumberable / IQueryable (?) rather than a list, this way I can further query and then executes only it is ready to be used. It's like we're kindof missing a ToAsyncEnumerable/ToAsyncQueryable solution. – DanAbdn Jan 24 '16 at 13:20
  • @DanAbdn Your premise is incorrect. There is nothing to await with an IQueryable return type since it is merely an expression that hasn't been resolved. You should always return simply `IQueryable` at lower levels and await your response resolving with `.ToListAsync()` when you are happy with the state of your expression. In other words, await and resolve in the same statement block and build simple queryable expressions elsewhere. – David L Jan 25 '16 at 16:56
  • @DavidL I agree with @DanAbdn that we're missing a `ToAsyncQueryable` method. I have [a situation](http://stackoverflow.com/questions/40560915) that could use it. – HappyNomad Nov 15 '16 at 06:10
  • 1
    @DanAbdn I went ahead and [requested](https://github.com/Reactive-Extensions/Rx.NET/issues/294) this feature. – HappyNomad Nov 15 '16 at 06:50