Как изменить значения нескольких свойств из одного списка в другой, используя LINQ C #: - PullRequest
0 голосов
/ 08 января 2019

У меня есть два списка, как

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 голосов
/ 08 января 2019

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;

Увы, это не сработает, если у вас есть 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();
0 голосов
/ 08 января 2019

Вам необходимо объединить оба списка для свойства 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

0 голосов
/ 08 января 2019

Вы хотите выполнить операцию join (скорее всего, внутреннее соединение). LINQ предоставляет такую ​​функцию

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

Но, как говорит @Martin Zikmund, я буду осторожен с манипулированием данными напрямую.

0 голосов
/ 08 января 2019

Вы можете циклически просматривать пары клиентских и корреспондентских заказов и обновлять клиентов только для соответствующих пар.

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 обновит клиента с использованием идентификатора заказа, который произошел последним в коллекции.

Методы расширения LINQ, разработанные «функциональным» образом, где перечисленные элементы обрабатываются как неизменяемые. Методы LINQ всегда возвращают новый экземпляр коллекции. Большинство разработчиков будут «очень» удивлены, если элементы будут видоизменяться во время методов перечисления.
Таким образом, наличие явного цикла foreach ясно скажет другим разработчикам о ваших намерениях.

0 голосов
/ 08 января 2019

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 более читабельным решением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...