我有两个类似
的列表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有人可以在这里纠正我吗?
答案 0 :(得分:4)
LINQ主要适合查询而不是数据修改。
相反,我只使用简单的foreach
:
foreach (var c in customer)
{
var o = order.FirstOrDefault(o => o.CustomerName == c.Name);
c.OrderId = o?.Id ?? 0;
}
当然,当每个客户有多个订单时,这种方法将无法正常工作。另外,我建议将变量重命名为复数-customers
和orders
,以更好地表示其含义。
对于纯粹的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();
输出: