简体   繁体   English

列表<T>加入数据表

[英]List<T> joins DataTable

I have a List of objects (lst) and DataTable (dt).我有一个对象列表(lst)和数据表(dt)。 I want to join the lst and dt on the common field (code as string) and need to return all matching rows in the lst.我想在公共字段(代码为字符串)上加入 lst 和 dt,并且需要返回 lst 中的所有匹配行。

My List contains two columns ie code and name along with values below:我的列表包含两列,即代码和名称以及以下值:

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

The DataTable contains two columns ie code and value along with values below: DataTable 包含两列,即代码和值以及以下值:

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

The result is:结果是:

3   z

Below is my code;下面是我的代码; but I know it is not a correct statement and thus seeking your advice here.但我知道这不是一个正确的陈述,因此在这里寻求您的建议。 I would be much appreciated if you could guide me on how to write the correct statement.如果您能指导我如何写出正确的陈述,我将不胜感激。

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

You can try any of the below.您可以尝试以下任何一种。

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 });

You can use Linq query or Join extension method to join the collection on code.您可以使用 Linq 查询或 Join 扩展方法在代码上加入集合。 Just that when you select data from datatable, you need to use dt.Field method.只是当您从数据表中选择数据时,您需要使用 dt.Field 方法。 Please use either of the following code.请使用以下任一代码。

Query1:查询 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();

Query2:查询 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();

Query3:查询 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();

It's not clear what your required output is but it looks as if you are correctly getting the only common records.目前尚不清楚您需要的输出是什么,但看起来您正确地获得了唯一的公共记录。 You could extend your select to您可以将select扩展到

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

Which would give all the data/columns from both tables.这将提供两个表中的所有数据/列。

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

Try this:尝试这个:

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 };

SO you have a List and a DataTable.所以你有一个列表和一个数据表。 You don't plan to use the Values of the DataTable, only the Codes.您不打算使用数据表的值,只使用代码。

You want to keep those List items, that have a Code that is also a code in the DataTable.您希望保留那些具有代码也是数据表中的代码的列表项。

If you plan to use your DataTable for other things than just for this problem, My advice would be to first create a procedure to convert your DataTable into an enumerable sequence.如果您计划将 DataTable 用于其他用途,而不仅仅是为了解决这个问题,我的建议是首先创建一个过程将您的 DataTable 转换为可枚举序列。

This way you can add LINQ statements, not only for this problem, but also for other problems.这样你就可以添加 LINQ 语句,不仅针对这个问题,还针对其他问题。

Let's create an extension method for your DataTable that converts the data into the items that are in the DataTable.让我们为您的 DataTable 创建一个扩展方法,将数据转换为 DataTable 中的项目。 See extension methods demystified.请参阅揭秘扩展方法。

Alas, I don't know what's in your DataTable, let's assume that your DataTable contains Orders唉,我不知道你的 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;} 
    ...
}

The extension method that extends functionality of class DataTable:扩展类 DataTable 功能的扩展方法:

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

I'm not really familiar with DataTables, but you know how to convert the cells of the row into the proper value.我对 DataTables 不是很熟悉,但您知道如何将行的单元格转换为正确的值。

Usage:用法:

DataTable table = ...
Int customerId = 14;

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

In words: convert the datatable into CustomerOrders, row by row, and check for every converted CustomerOrder whether it has a CustomerId equal to 14. Stop if found.换句话说:将数据表逐行转换为 CustomerOrders,并检查每个转换后的 CustomerOrder 是否具有等于 14 的 CustomerId。如果找到则停止。 return null if there is no such row.如果没有这样的行,则返回 null。

Now that you've got a nice reusable procedure that is also easy to test, debug and change, we can answer your question.既然您已经有了一个很好的可重用程序,并且也易于测试、调试和更改,我们可以回答您的问题。

Given a DataTable with CustomerOrders, and a sequence of items that contain Code and Name , keep only those items from the sequence that have a Code that is also a Code in the DataTable.给定一个带有 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();

This will create an enumerable sequence that will convert your DataTable row by row and extract property Code.这将创建一个可枚举序列,它将逐行转换您的 DataTable 并提取属性代码。 Duplicate Code values will be removed.重复的代码值将被删除。

If Codes are unique, you don't need Distinct.如果 Codes 是唯一的,则不需要 Distinct。

Note: the enumerable sequence is not enumerated yet!注意:可枚举序列还没有被枚举!

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

In words: for every [Code, Name] combination in your list, keep only those [Code, Name] combinations that have a value for Code that is also in codesInDataTable .换句话说:对于列表中的每个 [Code, Name] 组合,只保留那些具有 Code 值的 [Code, Name] 组合也在codesInDataTable

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

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