如何在 WinForm 中使用 LINQ 或 lambda return 任务列表

How to return Task list using LINQ or lambda in WinForm

我想在我的 LINQ 函数中使用 async 和 await 函数,但我不知道如何使用。我有两个表 Order 和 Product 我想加入它们并使用 async 在 DataGridView 中弹出。
这是我的异步函数。
我的列表定义是:

List<OrderDTO> transactionByDate;

和我的函数:

private async Task<List<OrderDTO>> GetTransactionByDate(DateTime today)
{
  return await Task.Factory.StartNew(() =>
   {
    using (Db db = new Db())
    {
       var totalOrder = (from u in db.Orders
                         join p in db.Product on u.ProductId equals p.ProductId
                         where u.OrderDate == today
                         select new OrderDTO
                         {
                           OrderId = u.OrderId,
                           ProductName = p.ProductName,
                           Date = u.OrderDate,
                           Price = u.Price,
                         }).OrderByDescending(x => x.Date).ToList();
                   return totalOrder;
                }
            });
        }

然后在我的按钮事件中:

private async void button1_Click(object sender, EventArgs e)
{
  transactionByDate = await GetTransactionByDate(today);
  dgvTransactions.DataSource = transactionByDate;
}

我得到的错误是:

The entity or complex type 'OrderDTO' cannot be constructed in a LINQ to Entities query.

我真的不知道如何从我的异步 GetTransactionByDate(today) 函数中 return。如果你能帮助我,我将不胜感激,我是这种编码的新手。

我无法测试它,因为它不能在本地编译(显然),但我认为你可以这样做:

private async Task<List<OrderDTO>> GetTransactionByDate(DateTime today)
{
    return await Task.Factory.StartNew(() =>
    {
        using (Db db = new Db())
        {
            var totalOrder = (from u in db.Orders
                              join p in db.Product on u.ProductId equals p.ProductId
                              where u.OrderDate == today
                              select new
                              {
                                  OrderId = u.OrderId,
                                  ProductName = p.ProductName,
                                  Date = u.OrderDate,
                                  Price = u.Price
                              })
                              .ToList();

            var result = totalOrder.Select(ano =>
                           new OrderDTO
                           {
                               OrderId = ano.OrderId,
                               ProductName = ano.ProductName,
                               Date = ano.OrderDate,
                               Price = ano.Price,
                           })
                           .OrderByDescending(x => x.Date)
                           .ToList();

            return result;
        }
    }
}

关键是要将数据库中发生的事情与内存中发生的事情分开。

不过,在你开始之前,我会创建一个很好的辅助函数,它可以去掉一些样板代码。

private async Task<List<T>> GetDtosAsync<T>(Func<Db, List<T>> getDtos) =>
    await Task.Run(() =>
    {
        using (Db db = new Db())
        {
            return getDtos(db);
        }
    });

请注意,我使用的是 Task.Run,因为 Task.Factory.StartNew 已过时且不再推荐。

现在你可以这样写你的方法了:

private async Task<List<OrderDTO>> GetTransactionByDate(DateTime today) =>
    await GetDtosAsync(db =>
    {
        var query =
            from u in db.Orders
            join p in db.Product on u.ProductId equals p.ProductId
            where u.OrderDate == today
            select new
            {
                u.OrderId,
                p.ProductName,
                u.OrderDate,
                u.Price,
            };
                    
        var totalOrder =
            query
                .ToList()
                .Select(x => new OrderDTO
                {
                    OrderId = x.OrderId,
                    ProductName = x.ProductName,
                    Date = x.OrderDate,
                    Price = x.Price,
                })
                .ToList();
        
        return totalOrder;
    });

query.ToList() 从数据库中获取数据并将其存入内存,然后再构建最终列表。