繁体   English   中英

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

[英]How to change values of few properties from one list to another using LINQ C#:

我有两个清单

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 list OrderId value from order list when CustomerName is matching with Name prop替换customer list OrderId value from order list when CustomerName is matching with Name prop

我正在尝试这样的事情-

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

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

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更具可读性的解决方案。

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;

las,如果您有多个OrdersCustomer ,这将不起作用:

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 OrdersCustomer 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();

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

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

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

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

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循环将清楚地告诉其他开发人员您的意图。

您需要将customer的属性Name和order的属性CustomerName都加入列表,然后从Order分配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();

输出:

在此处输入图片说明

暂无
暂无

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

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