繁体   English   中英

列表<T>加入数据表

[英]List<T> joins DataTable

我有一个对象列表(lst)和数据表(dt)。 我想在公共字段(代码为字符串)上加入 lst 和 dt,并且需要返回 lst 中的所有匹配行。

我的列表包含两列,即代码和名称以及以下值:

code name
==== ====    
1    x    
2    y    
3    z

DataTable 包含两列,即代码和值以及以下值:

code value
==== =====    
3    a    
4    b    
5    c

结果是:

3   z

下面是我的代码; 但我知道这不是一个正确的陈述,因此在这里寻求您的建议。 如果您能指导我如何写出正确的陈述,我将不胜感激。

var ld = from l in lst
         join d in dt.AsEnumerable() on l.code equals d.code
         select new { l.code, l.name };

您可以尝试以下任何一种。

var ld = from l in lst
     join d in dt.AsEnumerable() on l.code equals d.Field<int>("code")
     select new { l.code, l.name };

var ld = lst.Join(dt.AsEnumerable(), l => l.code, d => d.Field<int>("code"), (l,d) => new { l.code, l.name });

您可以使用 Linq 查询或 Join 扩展方法在代码上加入集合。 只是当您从数据表中选择数据时,您需要使用 dt.Field 方法。 请使用以下任一代码。

查询 1:

var ld = lst.Join(dt.AsEnumerable(),
            l => l.code,
            d => d.Field<string>("code"),
            (l, d) => new
            {
                l.code,
                l.name,
                value = d.Field<string>("value")
            }).ToList();

查询 2:

var ld = (from l in lst
          join d in dt.AsEnumerable()
          on l.code equals d.Field<string>("code")
          select new
          {
              l.code,
              l.name,
              value = d.Field<string>("value")
          }).ToList();

查询 3:

var ld = (from l in lst
          join d in dt.AsEnumerable()
          on l.code equals d.Field<string>("code")
          let value = d.Field<string>("value")
          select new
          {
              l.code,
              l.name,
              value
          }).ToList();

目前尚不清楚您需要的输出是什么,但看起来您正确地获得了唯一的公共记录。 您可以将select扩展到

select new { l.code, l.name, d.value }

这将提供两个表中的所有数据/列。

code name value
==== ==== =====
  3    z     a

尝试这个:

var ld = from l in lst
         join d in dt.Cast <DataRow>() on l.code equals d["code"].ToString()
         select new { l.code, l.name };

所以你有一个列表和一个数据表。 您不打算使用数据表的值,只使用代码。

您希望保留那些具有代码也是数据表中的代码的列表项。

如果您计划将 DataTable 用于其他用途,而不仅仅是为了解决这个问题,我的建议是首先创建一个过程将您的 DataTable 转换为可枚举序列。

这样你就可以添加 LINQ 语句,不仅针对这个问题,还针对其他问题。

让我们为您的 DataTable 创建一个扩展方法,将数据转换为 DataTable 中的项目。 请参阅揭秘扩展方法。

唉,我不知道你的 DataTable 中有什么,让我们假设你的 DataTable 包含Orders

class CustomerOrder
{
    public int Id {get; set;}
    public int CustomerId {get; set;}

    public int Code {get; set;}
    public string Value {get; set;} 
    ...
}

扩展类 DataTable 功能的扩展方法:

public static IEnumerable<Order> ToCustomerOrders(this DataTable table)
{
    return table.AsEnumerable().Select(row => new CustomerOrder
    {
        Id = ...
        CustomerId = ...
        Code = ...
        Value = ...
     };
}

我对 DataTables 不是很熟悉,但您知道如何将行的单元格转换为正确的值。

用法:

DataTable table = ...
Int customerId = 14;

var ordersOfThisCustomer = table.ToCustomerOrders
    .Where(customerOrder => customerOrder.CustomerId == customerId)
    .FirstOrDefault();

换句话说:将数据表逐行转换为 CustomerOrders,并检查每个转换后的 CustomerOrder 是否具有等于 14 的 CustomerId。如果找到则停止。 如果没有这样的行,则返回 null。

既然您已经有了一个很好的可重用程序,并且也易于测试、调试和更改,我们可以回答您的问题。

给定一个带有 CustomerOrders 的 DataTable,以及一个包含CodeName项目序列,只保留序列中那些 Code 也是 DataTable 中的 Code 的项目。

var dataTable = ...   // your DataTable, filled with CustomerOrders.
var codeNames = ...   // your list with Codes and Names

var codesInDataTable = dataTable.ToCustomerOrders
    .Select(customerOrder => customerOrder.Code)
    .Distinct();

这将创建一个可枚举序列,它将逐行转换您的 DataTable 并提取属性代码。 重复的代码值将被删除。

如果 Codes 是唯一的,则不需要 Distinct。

注意:可枚举序列还没有被枚举!

var result = codeNames
    .Where(codeName => codesInDataTable.Contains(codeName.Code))
    .ToList();

换句话说:对于列表中的每个 [Code, Name] 组合,只保留那些具有 Code 值的 [Code, Name] 组合也在codesInDataTable

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM