-1

In following LinQ query to get Phone Number I'm calling another async method GetAspNetUserPhoneNumberByAccountId, which throws this error

Error CS4034 The 'await' operator can only be used within an async lambda expression. Consider marking this lambda expression with the 'async' modifier.

Anyone have idea about it ?

 var fullAppointment = await Task.Run(() => Context.AppointmentDetail
     .Where(u =>
     u.StartDateTime >= startdatetime
      && u.EndDateTime <= enddatetime

      )
       .Select(x => new Contracts.CalenderModel2()
        {
          StatusId = (Contracts.Enum.EnumWOStatus)x.Status,
          FName = x.Appointment != null ? x.Appointment.Customer.Account.FName : "",
          LName = x.Appointment != null ? x.Appointment.Customer.Account.LName : "",
          **PrimaryPhone = x.Appointment != null ?
          (await _userRepository.GetAspNetUserPhoneNumberByAccountId( x.Appointment.Customer.AccountId))**
          : "",
          Year = x.Appointment != null && x.Appointment.Vehicle != null ? x.Appointment.Vehicle.MakeYear.Year : 0,
          Make = x.Appointment != null && x.Appointment.Vehicle != null ? x.Appointment.Vehicle.VehicleMaker.MakerName : "",
          Model = x.Appointment != null && x.Appointment.Vehicle != null ? x.Appointment.Vehicle.VehicleModel.Model : "",
          AppointmentId = x.AppointmentId,
          JobEndDateTime = x.EndDateTime,
          JobStartDateTime = x.StartDateTime,
          ColorCategory = x.AppointmentType.ColorCategory,

          SalesRepersentativeUserId =
(x.Appointment != null && x.Appointment.Customer.CustomerBillTo.Count > 0)
              ? x.Appointment.Customer.CustomerBillTo.FirstOrDefault().BillToId : Guid.Empty,

          FullAppointmentDetail = new Contracts.FullAppointmentDetail
          {
            BayId = x.BayId,
            BayName = x.WorkArea != null ? x.WorkArea.BayName : "",
            WorkTypeId = x.WorkTypeId,
            WorkTypeName = x.WorkType != null ? x.WorkType.WorkTypeName : "",
            JobId = x.Appointment != null && x.Appointment.Job != null ? x.Appointment.Job.Id : Guid.Empty,
            JobIdInt = x.Appointment != null && x.Appointment.Job != null ? x.Appointment.Job.JobIdInt : 0,
            AssigneeUserId = x.AssigneeUserId,
            WorkOrderId = x.WorkOrders.FirstOrDefault() != null ? x.WorkOrders.FirstOrDefault().Id : Guid.Empty
          }

        })
        .ToList());

The Definition of GetAspNetUserPhoneNumberByAccountId is given below

public async Task<string> GetAspNetUserPhoneNumberByAccountId(Guid accountId)
{
  var phone = await Task.Run(() => _Context.Account.Where(ac => ac.Id.Equals(accountId))
   .Join(_Context.AspNetUsers, ac => ac.AspNetUserId, u => u.Id, (ac, u) => new 
   {
     PhoneNumber = u.PhoneNumber,

   }).FirstOrDefault());

  return phone!=null?phone.ToString():"";
}
Hans Kesting
  • 38,117
  • 9
  • 79
  • 111
  • 4
    Why are you using `Task.Run` in either of these methods? Re the specific question, there are [plenty of duplicates](https://stackoverflow.com/questions/20593501/the-await-operator-can-only-be-used-within-an-async-lambda-expression?rq=1) on this site. But I don't think you should be using `async` here in the first place. – Charles Mager Feb 15 '19 at 12:21
  • Why do you need an await? The method is not async so it will automatically wait. – jdweng Feb 15 '19 at 12:22
  • 1
    Apart from the questions about why you're using `Task.Run` and if you need await. Just call `Task.Run(async () => {…` should get rid of this error –  Feb 15 '19 at 12:23
  • 1
    @Knoop I think you'd actually need to add `async` to the lambda in `Select` too. You then have a query that returns `IEnumerable>` which you'd have to use `Task.WhenAll` on. – Charles Mager Feb 15 '19 at 12:25
  • @CharlesMager you're right. All anonymous functions containing await operations should be async. for completion, that would look like this: `.Select(async x =>…` –  Feb 15 '19 at 12:31
  • I used Task.Run for wait. – Devendra Lodha Feb 19 '19 at 05:18
  • I tried Task.Run(async () =>.... but when I used that another error came; actually return type of method GetAspNetUserPhoneNumberByAccountId is Task so compiler says, cann't implicit convert Task to string. – Devendra Lodha Feb 19 '19 at 05:21

1 Answers1

0

I agree with guys in the comments that you don't need to use async method in this query. In additional this query will not optimize. For each item in Where condition you will do it query to DB. If you have a lot of data, performance of DB will go down. I think in this case much better to do it 2 queries to DB. For getting AppointmentDetail and another query for getting all accounts. And both query call with async. And after that combine it to your Contracts.CalenderModel2 class.

It will be more readable and work faster. And don't use Task.Run();

Nick Sinitsin
  • 247
  • 1
  • 4