如何使用LINQ C#将几个属性的值从一个列表更改为另一个:

时间:2019-01-08 09:51:25

标签: c# linq c#-4.0

我有两个类似

的列表
List<Customer> customer = new List<Customer>() 
 { Id =1 , Name = 'Demo1' , OrderId = 123}
 { Id =1 , Name = 'Demo2' , OrderId = 123}

List<Order> order = new List<Order>() 
{ Id =77 , CustomerName = 'Demo1'}
{ Id =88 , CustomerName = 'Demo2'}

我要替换customer.OrderId = order.Id where order.CustomerName = customer.Name

我要替换customer list OrderId value from order list when CustomerName is matching with Name prop

我正在尝试类似的事情-

customer = order.Select(eo => new Customer { Name = eo.CustomerName });

这不正确LINQ有人可以在这里纠正我吗?

5 个答案:

答案 0 :(得分:4)

LINQ主要适合查询而不是数据修改。

相反,我只使用简单的foreach

foreach (var c in customer)
{
    var o = order.FirstOrDefault(o => o.CustomerName == c.Name);
    c.OrderId = o?.Id ?? 0;
}

当然,当每个客户有多个订单时,这种方法将无法正常工作。另外,我建议将变量重命名为复数-customersorders,以更好地表示其含义。

对于纯粹的LINQ方法,您可以编写ForEach LINQ扩展方法,但我发现显式的foreach更易读。

答案 1 :(得分:2)

LINQ主要用于查询。您可以创建一个符合您要求的新列表。

如果需要,您可以将此新列表分配给您的可变客户。

您想加入客户并以客户的名义下订单。

简单的解决方案:

var joinResult = customers.Join(orders,    // join the tables of customers with orders
    customer => customer.Name,             // from every customer take the Name
    order => order.CustomerName,           // from every order take the CustomerName
    (customer, order) => new Customer      // when they match make a new Customer
    {
        Id = customer.Id,                  // take Id and Name from the matching Customer
        Name = customer.Name,
        OrderId = order.Id,                // take the OrderId from the matching order
    })
    .ToList();
customers = joinResult;

A,如果您的Customer中有多个Orders,则无法使用:

var customers = new List<Customer>() 
    { Id = 1 , Name = 'John Doe' , OrderId = 123},

var orders = new List<Order>() 
    { Id =77 , CustomerName = 'John Doe'}
    { Id =88 , CustomerName = 'John Doe'}

客户1是否应具有OrderId 77或78?

您确定每个客户只有一个订单吗?

要获取Customer with all his Orders,请使用GroupJoin

var result = customers.GroupJoin(orders, // GroupJoin the customers with orders
    customer => customer.Name,           // from every customer take the Name
    order => order.CustomerName,         // from every order take the CustomerName
    (customer, orders) => new            // for every customer with all his matching orders
    {                                    // make one new object
        Id = customer.Id,                  // take Id and Name from the matching Customer
        Name = customer.Name,

        // TODO Decide what to do if there are several orders for customer with this name
        // Keep all orders? Or keep the oldest one, the newest one?
        // the unpaid ones?
        AllOrders = orders.ToList(),
        OldestOrder = orders.Orderby(order => order.Date).FirstOrDefault(),
        NewestOrder = orders.OrderByDescending(order => order.Date).FirstOrDefault(),
        UnpaidOrders = orders.Where(order => order.Status == Status.Unpaid).ToList(),
    })
    .ToList();

答案 2 :(得分:1)

您要执行 join 操作(很可能是内部联接)。 LINQ提供了这样的功能

var customerOrders = customer.Join(order,
    c => c.Name,
    o => o.CustomerName,
    (customer, order) =>
    {
        custumer.OrderId= order.Id;
        return customer;
    }).ToList();

但是正如@Martin Zikmund所说,我将谨慎处理直接的数据。

答案 3 :(得分:1)

您可以遍历一对客户订单和对应的订单,并仅更新匹配的客户对。

var matched = customers.Join(orders,
                             customer => customer.Name,
                             order => order.CustomerName,
                             (customer, order) => (Customer: customer, Order: order));

foreach (var pair in matched)
{
    pair.Customer.OrderId = pair.Order.Id;
}

请注意,如果订单集合包含多个具有相同客户名称的订单,则Join方法将使用集合中最后出现的订单ID更新客户。

LINQ扩展方法以“功能性”方式设计,其中枚举项被视为不可变的。 LINQ方法始终返回该集合的新实例。如果在枚举方法期间项目发生突变,大多数开发人员将“非常”惊讶。
因此,拥有明确的foreach循环将清楚地告诉其他开发人员您的意图。

答案 4 :(得分:1)

您需要同时加入客户的属性Name和订单的属性CustomerName的两个列表,然后从订单中分配OrderId,例如

List<Customer> result = new List<Customer>();

result = (from c in customer
          join o in order on c.Name equals o.CustomerName
          select new Customer
          {
              Id = c.Id,
              Name = c.Name,
              OrderId = o.Id
          }).ToList();

foreach (var item in result)
{
    Console.WriteLine($"Id: {item.Id}, \t Name: {item.Name}, \t OrderId: {item.OrderId}");
}

Console.ReadLine();

输出:

enter image description here