使用Lambda表达式查询SQL语句填充的DataTable

Posted

技术标签:

【中文标题】使用Lambda表达式查询SQL语句填充的DataTable【英文标题】:Using Lambda expressions to query DataTable filled by SQL statement 【发布时间】:2019-12-08 11:21:27 【问题描述】:

我正在构建一个 WinForm,它在 DataGridView 中显示每个客户的约会次数。我可以使用基本的 SELECT 语句来做到这一点,但要求至少需要 2 个 Lambda 表达式。我创建了 1 个 Lambda 表达式,但到目前为止它什么也没做。据我了解,Lambda 可用于查询 DataTable,类似于 SQL 语句查询表的方式。但由于某种原因,什么都没有发生。 DataTable 填得很好,但 Lambda 什么也没做。

这是 WinForm 的全部代码:

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using mysql.Data.MySqlClient;
using System.Data.Entity;
using System.Data.Linq;


namespace C969_Software_2

public struct Customer

    public string customerName;
    public int numberOfApps;


public partial class CustomerReports : Form

    public CustomerReports()
    
        InitializeComponent();
        customerReportView.DataSource = getReport();
    


    public static DataTable getReport()
    
        string SqlString = "SELECT * FROM customer";
        MySqlConnection c = new MySqlConnection(SqlUpdater.conString);
        MySqlDataAdapter sda = new MySqlDataAdapter(SqlString, c);
        DataTable dt = new DataTable();

        c.Open();
        sda.Fill(dt);
        dt.AsEnumerable()
            .Where(i => i.Field<int>("customerId") == 1)
            .Select(i => new  name = i.Field<string>("customerName"));

     return dt;
    


任何指针将不胜感激!

【问题讨论】:

没有告诉 Lamba 函数做任何事情。这就像一个固定查询,直到需要才执行。您可以通过附加.ToArray().ToList() 使其运行。 AlwaysLearning:感谢您的提示!现在我看到了一些人们能够使用 .CopyToDataTable() 的实例,但在这种情况下似乎不起作用。 .CopyToDataTable() 在这里不起作用,因为它需要 IEnumerable&lt;DataRow&gt; 作为源,而您选择的是 IEnumerable&lt;SomeAnonymousObject&gt;。即:您的 .Select() 语句正在返回一个新对象。 @PatrickDavis,另外,请在用户名前添加@ 符号,以便他们得到通知。 【参考方案1】:

假设您的 Linq 查询的目的是获取 customerId 1 的名称,请尝试以下操作...

//This creates the query as IEnumerable<someAnonymousRuntimeObject> but doesn't execute it.
var query = dt.AsEnumerable()
    .Where(i => i.Field<int>("customerId") == 1)
    .Select(i => new  name = i.Field<string>("customerName") );

//This actually executes the query and stores the result in name
var name = query.FirstOrDefault().name;

=== 编辑 ===

对于您期望从 getReport() 返回的内容有点模糊。

如果正如您的 Linq Select 语句所建议的那样,您只想要 customerName 代替 customerId == 1,您可以这样做:

var name = dt.AsEnumerable()
    .Where(i => i.Field<int>("customerId") == 1)
    .Select(i => i.Field<string>("customerName"))
    .FirstOrDefault();
return name;

如果你想要一个 DataTable 只包含 customerId == 1 所在的行,你可以这样做:

var dt2 = dt.AsEnumerable()
    .Where(i => i.Field<int>("customerId") == 1)
    .CopyToDataTable();
return dt2;

这会返回一行,其中包含 customerId、customerName 以及您的 SELECT * 语句返回的任何其他列。

不过,上述方法都不是特别有效。随着您的数据库增长并且客户表包含数千或数百万行,您将向您的 C# 代码返回数千或数百万行,以过滤为仅一行。最好让 SQL 为您进行过滤并仅将所需的单行返回给您的 C# 代码。

您可以使用参数化查询来执行此操作,例如:

public static DataTable getReportById(int customerId)

    using (var conn = new MySqlConnection(SqlUpdater.conString))
    using (var cmd = conn.CreateCommand())
    
        cmd.CommandText = "SELECT customerName as 'name' FROM customer where customerId = @Id";
        cmd.Parameters.AddWithValue("@Id", customerId);
        MySqlDataAdapter sda = new MySqlDataAdapter(cmd);
        DataTable dt = new DataTable();
        sda.Fill(dt);
        return dt;
    

【讨论】:

感谢您的帮助!这似乎不起作用。我只是不断得到同样的东西。我认为这可能是因为 return.dt 但在注释掉之后,getReport 方法没有任何返回... 基本上我试图从数据库中获取一些列,将它们放入数据表中,然后使用 Linq 查询过滤数据表,并将结果显示在 datagridview 中 谢谢!这是一个很大的帮助!我意识到它的效率相当低,但它是一个小型测试数据库,并且使用 Linq/Lambda 是要求的一部分。通常我会使用参数。

以上是关于使用Lambda表达式查询SQL语句填充的DataTable的主要内容,如果未能解决你的问题,请参考以下文章

sql语句-linq语言-lambda表达式对照

LINQ TO SQL

动态构建Lambda表达式实现EF动态查询

Sql LinqLambda 查询语句的区别

sql linqlambda 查询语句的区别

获取EF查询的SQL语句