【问题标题】:c# winforms How do I use async await using LINQc# winforms 如何使用 LINQ 使用异步等待
【发布时间】:2021-01-29 15:34:30
【问题描述】:

我想使用异步等待功能按年龄分组。没有 aync 等待它工作正常,但我想要 使用异步等待。 如果我在第一行中排除 ToList() ...从 db.Patient.ToList() 中的 u ... 那么我会遇到 CalculateAge 函数的问题 错误 LINQ Entities 在方法 CalculateAge(system.String).. 中无法识别 这就是为什么在那里使用它。 CalculateAge 函数是计算年龄,这里是代码函数

private int CalculateAge(string birthday)
        {
            int age;
            if (string.IsNullOrWhiteSpace(birthday)) return 0;

            DateTime empBirthday = Convert.ToDateTime(birthday);
            DateTime today = DateTime.Today;
            age = today.Year - empBirthday.Year;
            if (empBirthday > today.AddYears(-age))
                age--;
            return age;
        }

没有异步等待也可以正常工作

private void btnByAge_Click(object sender, EventArgs e)
{
    var result = (from u in db.Patient.ToList() // 
                  join a in db.Analys on u.PatientId equals a.PatientId
                  where a.Status == Active
                  group u by CalculateAge(u.DOB.ToString()) into g
                  select new
                  {
                      Age = g.Key,
                      Amount = g.Count(),
                  }).Tolist();

    if (result != null)
    {
        dgvResult.DataSource = result;
    }
}

但异步等待不是这个

private async void btnByAge_Click(object sender, EventArgs e)
{
    var result = (from u in db.Patient.ToListAsync()
                  join a in db.Analys on u.PatientId equals a.PatientId
                  where a.Status == Active
                  group u by CalculateAge(u.DOB.ToString()) into g
                  select new
                  {
                      Age = g.Key,
                      Amount = g.Count(),
                  });

    var data = await result.ToListAsync();
    if (data != null)
    {
        dgvResult.DataSource = data;
    }
}

我得到的错误是错误 CS1936 找不到源类型“任务>”的查询模式的实现。未找到“加入”... 我什至使用过 Using.System.Data.Linq ,但同样的问题。请帮忙,提前谢谢!

【问题讨论】:

  • 您需要等待db.Patient.ToListAsync() 的来电。最好在 DB 上进行 join 和 where 过滤,然后调用 AsEnumerable,以便您可以在 group by 中调用 CalculateAge。或者甚至更好地将 CalculateAge 所做的任何事情翻译成可以翻译成 SQL 的代码。
  • @juharr 谢谢你的回复,但我是这种员工的新手,你能通过编码告诉我你的意思吗?
  • CalculateAge 是做什么的?你能提供它的实现吗?
  • 另外,CalculateAge 使用 string 而不是 DateTime,这很奇怪。

标签: c# linq asynchronous async-await


【解决方案1】:

修复错误所需要做的就是在db.Patient.ToListAsync() 之前添加一个await。但是,最好不要这样做ToList,以便可以在数据库中完成连接。另请注意,您不需要null 检查,因为结果永远不会是null(可能为空或可能会引发异常,但它们永远不应为空)

var dobs = await (from u in db.Patient
                  join a in db.Analys on u.PatientId equals a.PatientId
                  where a.Status == Active
                  select u.DOB).ToListAsync();
var data = dobs
    .GroupBy(x => CalculateAge(x.toString())
    .Select(grp => new
    {
        Age = grp.Key,
        Amount = grp.Count(),
    })
    .ToList();

dgvResult.DataSource = data;    

这将对状态进行连接和过滤,并选择数据库中的 DOB 并异步获取 DOB。然后您可以在内存中进行分组,因为CalculateAge 无法转换为 SQL。但更好的办法是在数据库中进行年龄计算。

var now = DateTime.UtcNow(); // or .Now() if you don't store UTC in the DB
var result =  from u in db.Patient
              join a in db.Analys on u.PatientId equals a.PatientId
              where a.Status == Active
              let age = now.Year - u.DOB.Year -
                  ((u.DOB.Month < now.Month || 
                      (u.DOB.Month == now.Month && u.DOB.Day < now.Day))
                  ? 1 : 0)
              group u by age into g
              select new
              {
                  Age = g.Key,
                  Amount = g.Count(),
              };

dgvResult.DataSource = await result.ToListAsync();    

通过从当前年份减去 DOB 年份来确定年龄,如果当前日期在 DOB 的月份和日期之前,则减去 1。

此外,如果您打算使用CalculateAge,则只需将DateTime 传递给它,而不是将其格式化为string,然后将其解析回DateTime。如果可能是null,您可以传递DateTime?

private int CalculateAge(DateTime? birthday)
{
    int age;
    if (!birthday.HasValue) return 0;

    DateTime today = DateTime.Today;
    age = today.Year - birthday.Value.Year;
    if (birthday.Value > today.AddYears(-age))
        age--;
    return age;
}

【讨论】:

  • 感谢您的回复。 CalculateAge 是计算年龄,我现在已经使用CalculateAge 函数编辑了我的原始帖子,你的解决方案如何计算年龄似乎更好,但我收到错误错误CS0019 运算符'-' 不能应用于'int' 和'bool 类型的操作数' ,我现在在某个地方的 int 和 bool 之间存在冲突。Year - u.DOB.Value.Year - (u.DOB.Value.Month
  • 是的,它还需要一组括号。
  • 太棒了,它现在完美运行。非常感谢,也谢谢大家的回复
  • 对不起,Juharr 打扰了,但我更喜欢使用带有函数 CaluculationAge 的第一个解决方案,但我在这里收到错误 var data = await result.ToListAsync();结果是我收到错误,例如 IEnumerable>' does not contain a definition for 'ToListAsync' 并且最佳扩展方法重载 'QueryableExtensions.ToListAsync(IQueryable)' 需要接收器类型'IQueryable'
  • 我已经更新了第一个。您必须执行 ToListAsync 而不是 AsEnumerable 然后您不需要空检查,因为它永远不会为空。
【解决方案2】:

没有什么特别的,你可以用 C# 来实现这个代码,看看下面的代码。

private async void button1_Click(object sender, EventArgs e)
    {
        var query = (from p in db.Patient
                     join An in db.Analys on p.PatientId equals An.PatientId
                     where An.Status == Active
                     select p.DOB)



       var Result=await query.GroupBy(x => CalculateAge(x.toString())
           .Select(g => new {
               Age = g.Key,
               Amount = g.Count(),
           }).ToListAsync();
 dgvResult.DataSource = Result
    }    

【讨论】:

    猜你喜欢
    • 2013-08-01
    • 1970-01-01
    • 2015-07-27
    • 2014-03-19
    • 2014-08-15
    • 1970-01-01
    • 1970-01-01
    • 2020-07-11
    • 2021-12-20
    相关资源
    最近更新 更多