Объединение двух списков с одинаковыми свойствами в один список

Ниже одна из моих сущностей:

[Table("UserPaymentAccountHistoryLog")]
public partial class UserPaymentAccountHistoryLog : IEntity
{
    public int UserPaymentAccountHistoryLogID { get; set; }

    public Guid UserID { get; set; }
    public Guid UserPaymentAccountID { get; set; }
    public bool ActionType { get; set; }
    public DateTime LogHistory { get; set; }

    [Required]
    [StringLength(100)]
    public string LogDetail { get; set; }

    public virtual UserPaymentAccount UserPaymentAccount { get; set; }
}

И это мое другое лицо:

[Table("UserPaymentHistoryLog")]
public partial class UserPaymentHistoryLog : IEntity
{
    [Key]
    public int UserPaymentHistoryLogID { get; set; }

    public Guid UserPaymentAccountID { get; set; }
    public Guid UserID { get; set; }
    public Guid OrderID { get; set; }
    public bool TransactionType { get; set; }
    public DateTime LogHistory { get; set; }

    [Required]
    [StringLength(100)]
    public string LogDetail { get; set; }
}

Как видите, некоторые из их свойств совпадают. Я пытаюсь объединить два списка, которые состоят из этих двух сущностей, в один список, который состоит ниже сущности:

public class CardTransactionHistoryWM
{
    public bool ActionType { get; set; }
    public bool TransactionType { get; set; }
    public DateTime LogHistory { get; set; }
    public string LogDetail { get; set; }
    public OrderWM Order { get; set; }
}

Я сталкиваюсь с решениями, предлагаю использовать запросы linq join и zip, но те же свойства продолжают меня смущать.

Важная часть заключается в том, что если UserPaymentAccountHistoryLog и UserPaymentHistoryLog имеют одинаковые записи дат, CardTransactionHistoryWM должен опубликовать одну строку, а не две, для этой даты и отобразить как UserPaymentAccountHistoryLog, так и UserPaymentHistoryLog LogDetails.

Заранее спасибо!

Что ж, мне интересно, почему один класс не может расширить другой здесь, и тогда у вас будет только один тип для объединения. В противном случае я бы использовал automapper для сопоставления с одним классом и concat

misha130 10.08.2018 17:15

Я предполагаю, что вам нужен список всех объектов в памяти, в этом случае вы можете использовать абстрактный базовый класс или интерфейс для обоих классов, и оттуда вы можете создать список <interface> для добавления объектов.

Aldert 10.08.2018 17:28

Я думаю, что не могу реализовать оба ваших предложения, поскольку эти объекты напрямую привязаны к таблицам базы данных.

RaZzLe 10.08.2018 20:06
Я думаю, что не могу реализовать оба ваших предложения - Почему нет? Вы можете сопоставить списки обоих классов спискам CardTransactionHistoryWM и объединить их.
Gert Arnold 11.08.2018 10:10
1
4
179
1

Ответы 1

Если методы соединения и / или zip слишком сложны или трудны для понимания, другой способ сделать это - расширить класс CardTransactionHistoryWM, включив в него:

  1. Статический метод Parse, который возвращает экземпляр класса на основе экземпляра UserPaymentHistoryLog.

  2. Статический метод Parse, который возвращает экземпляр класса на основе экземпляра UserPaymentAccountHistoryLog.

  3. Метод экземпляра MergeWith, который объединяет существующий экземпляр с экземпляром UserPaymentHistoryLog.

  4. Метод экземпляра MergeWith, который объединяет существующий экземпляр с экземпляром UserPaymentAccountHistoryLog.

Например:

public class CardTransactionHistoryWM
{
    public bool ActionType { get; set; }
    public bool TransactionType { get; set; }
    public DateTime LogHistory { get; set; }
    public string LogDetail { get; set; }
    public OrderWM Order { get; set; }

    public void MergeWith(UserPaymentHistoryLog uphl)
    {
        if (LogHistory != uphl.LogHistory)
            throw new InvalidOperationException("Cannot merge if LogHistory dates don't match");

        TransactionType = uphl.TransactionType;
        LogDetail = string.Concat(LogDetail, uphl.LogDetail);
    }

    public void MergeWith(UserPaymentAccountHistoryLog upahl)
    {
        if (LogHistory != upahl.LogHistory)
            throw new InvalidOperationException("Cannot merge if LogHistory dates don't match");

        ActionType = upahl.ActionType;
        LogDetail = string.Concat(LogDetail, upahl.LogDetail);
    }

    public static CardTransactionHistoryWM Parse(UserPaymentHistoryLog source)
    {
        return new CardTransactionHistoryWM
        {
            TransactionType = source.TransactionType,
            LogHistory = source.LogHistory,
            LogDetail = source.LogDetail
        };
    }

    public static CardTransactionHistoryWM Parse(UserPaymentAccountHistoryLog source)
    {
        return new CardTransactionHistoryWM
        {
            ActionType = source.ActionType,
            LogHistory = source.LogHistory,
            LogDetail = source.LogDetail
        };
    }
}

С добавлением этих методов вы можете затем использовать их при синтаксическом анализе ваших двух списков для создания нового экземпляра класса CardTransactionHistoryWM или для слияния с существующим экземпляром, если даты совпадают:

public static List<CardTransactionHistoryWM> Merge(
    List<UserPaymentAccountHistoryLog> userPaymentAccountHistoryLogs,
    List<UserPaymentHistoryLog> userPaymentHistoryLogs)
{
    var results = new List<CardTransactionHistoryWM>();

    foreach (var upahl in userPaymentAccountHistoryLogs)
    {
        var match = results.SingleOrDefault(cthwm => cthwm.LogHistory == upahl.LogHistory);

        if (match == null)
        {
            results.Add(CardTransactionHistoryWM.Parse(upahl));
        }
        else
        {
            match.MergeWith(upahl);
        }
    }

    foreach (var uphl in userPaymentHistoryLogs)
    {
        var match = results.SingleOrDefault(cthwm => cthwm.LogHistory == uphl.LogHistory);

        if (match == null)
        {
            results.Add(CardTransactionHistoryWM.Parse(uphl));
        }
        else
        {
            match.MergeWith(uphl);
        }
    }

    return results;
}

Другие вопросы по теме