5
\$\begingroup\$

I have an n-tier solution which consist of DAL,BL and a ASP.net WebAPI project. I'm new with Asynchronous Pattern and I'm trying to add it to my Framework. Am I using the asynchronous pattern correctly? I'm not convinced with my implementation of it. Could you give me a recommendation on how to use it correctly or any other improvements I can make on my system?

This is my BL.

 public async Task<DTOUserList> GetUserList(DTOSearch source)
            {
                var result = new DTOUserList();

                try
                {

                    string strQuery;
                    Object[] objValues;
                    string strOrderBy;
                    CommonFunctions.ParseQuery(out strQuery, out objValues, out  strOrderBy, source);
                    //This is my implementation of async/await which im not convinced.
                    result = await Task.Run(() => _RepositoryUser.GetUserList(strQuery, objValues, source.PageNo, source.PageSize, source.OrderBy));

                }
                catch (Exception ex)
                {
                    result.IsSuccessful = false;
                    result.ErrorMsg = "Business Layer Error - " + ex.Message;
                }

                return result;
            }

and this is my DAL.

public DTOUserList GetUserList(String Query, object[] values, Int32 pageNo, Int32 pageSize, String orderby)
        {
            var result = new DTOUserList();

            try
            {

                _Entities = new Entities();

                IQueryable<DTOUser> data = from user in _Entities.mdUsers
                                           where user.Deleted == 0
                                           select new DTOUser
                                           {
                                               UserID = user.UserID,
                                               FirstName = user.FirstName,
                                               MiddleName = user.MiddleName,
                                               LastName = user.LastName,
                                               Email = user.Email,
                                               Telephone = user.Telephone,
                                               Mobile = user.Mobile,
                                               Address = user.Address,
                                               City = user.City,
                                               Country = user.Country,
                                               Active = user.Active,
                                               DateCreated = user.DateCreated

                                           };

                if (!string.IsNullOrWhiteSpace(Query)) data = data.Where(Query, values);

                result.TotalRecords = data.Count();
                result.UserList = data.OrderBy(a => a.FirstName).Skip(((pageNo > 0 ? pageNo : 1) - 1) * (pageSize > 0 ? pageSize : 1000)).Take((pageSize > 0 ? pageSize : 1000)).ToList();
                result.IsSuccessful = true;

            }
            catch (Exception ex)
            {
                result.IsSuccessful = false;
                result.ErrorMsg = "Data Access Layer Error - " + ex.Message;
            }
            return result;

        }
\$\endgroup\$
3
\$\begingroup\$

In general, you shouldn't expose synchronous operations as asynchronous, see Should I expose asynchronous wrappers for synchronous methods? If a method doesn't have an async version, just expose it synchronously. The caller can then choose to run it on another thread, if that makes sense.

\$\endgroup\$
2
\$\begingroup\$

I can see your implementation as a nice example of async programming. Being async enables you to keep your UI responsive while waiting for the response. You may not be so convinced as you just need to make a call and why do you need to wait for it? But the reason is responsiveness of the UI that gives a nice impression to user while waiting for the results.

Async programming works best when you have multiple tasks to do for example you pull results from your db and perform some tasks on each of the record returned eg. send mail, process invoices, print faxes etc.

So as conclusion the concerned piece of code would only show responsive UI while waiting for the result if the db connection is slow of it take longer to respond. There is nothing wrong in your code and it is already optimized nicely.

\$\endgroup\$
  • \$\begingroup\$ Thanks for the review. there is a ToListAsync() function in EF6 that I want to use so I can make my DAL method async. but I need to upgrade my EF5 to EF6. do you think its necessary for me to upgrade my EF or should I just add my DAL method statements in a Task.Factory? \$\endgroup\$ – rcadaoas May 21 '14 at 9:27
2
\$\begingroup\$

You are not using the async pattern to its fullest potential. Whether that is as designed is up to you :-)

By catching exceptions, you are circumventing the built-in exception propagation flow of TAP.

 catch (Exception ex)
 {
      result.IsSuccessful = false;
      result.ErrorMsg = "Business Layer Error - " + ex.Message;
 }

This means callers should parse erorrs from your custom implementation rather than from common usage:

var task = GetUserList(source);
// won't have much effect, since errors are catched in the user list
task.ContinueWith(t => HandleError(t.Exception), TaskContinuationOptions.OnlyOnFaulted);

Or

try {
    var users = await GetUserList(source);
    // consumer needs to add boiler-plate code to handle all errors
    if (!users.IsSuccessful) {
       throw new ParseException(users); // DAL/BUS error
    }
} catch (Exception error) {
    HandleError(error);
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.