Search code examples
c#linq

Having trouble grouping data using GroupBy Linq


I have a transaction table that holds the following fields:

TransactionDataModel:

TransactionName (string)
TransactionType (string)
Amount (double)
DateProcess (DateTime)
IsCredit (bool)

I want to find the total amount of transactions done every day, so I am thinking I should group the data based on the DateProcess field and sum the Amount. But I am having issues implementing this in the backend using LINQ.

Here are the code snippets:

TransactionViewModel

public class TransactionViewModel : ViewModelBase
{
    private readonly TransactionStore _transactionStore;
    private readonly Func<IEnumerable<TransactionDataModel>, IEnumerable<TransactionDataModel>> _filterTransaction;
    private readonly ObservableCollection<TransactionDataModel> _transactions;

    public IEnumerable<TransactionDataModel> Transactions => _transactions;

    public TransactionViewModel(TransactionStore transactionStore) : this(transactionStore, transactions => transactions) { }

    public TransactionViewModel(TransactionStore transactionStore, Func<IEnumerable<TransactionDataModel>, IEnumerable<TransactionDataModel>> filterTransactions)
    {
        _transactionStore = transactionStore;
        _filterTransaction = filterTransactions;
        _transactions = new ObservableCollection<TransactionDataModel>();

        _transactionStore.StateChanged += Transaction_StateChanged;

        ResetTransactions();
    }

    private void ResetTransactions()
    {
        IEnumerable<TransactionDataModel> transactionDataModel = _transactionStore.TransactionList
            .Select(t => new TransactionDataModel(t.Transaction_Name, t.Process_Date, t.Amount, t.Transaction_Type, t.Is_Credit))
            .OrderByDescending(o => o.ProcessDate);

        transactionDataModel = _filterTransaction(transactionDataModel);

        _transactions.Clear();
        foreach (TransactionDataModel dataModel in transactionDataModel)
        {
            _transactions.Add(dataModel);
        }
    }

    private void Transaction_StateChanged()
    {
        ResetTransactions();
    }
}

TransactionStore

public class TransactionStore
{
    private readonly AccountStore _accountStore;

    public IEnumerable<TransactionDataModel> TransactionList => _accountStore.CurrentAccount?.TransactionList ?? new List<TransactionDataModel>();

    public event Action StateChanged;

    public TransactionStore(AccountStore accountStore)
    {
        _accountStore = accountStore;

        _accountStore.StateChanged += OnStateChanged;
    }

    private void OnStateChanged()
    {
        StateChanged?.Invoke();
    }
}

SpendingSummaryViewModel

public class SpendingSummaryViewModel : ViewModelBase
{
    private readonly TransactionStore _transactionStore;
    public TransactionViewModel TransactionViewModel { get; }
    private readonly IEnumerable<TransactionDataModel> _transactions;

    public IEnumerable<TransactionDataModel> Transactions => _transactions;

    public SpendingSummaryViewModel(TransactionStore transactionStore)
    {
        _transactions = new ObservableCollection<TransactionDataModel>();
        _transactionStore = transactionStore;
        TransactionViewModel = new TransactionViewModel(transactionStore, 
            transactions => transactions.Where(t => t.IsCredit==true)
            .GroupBy(t => t.ProcessDate.Date)
            .Select(g => new ChartDataModel
            {
                ProcessDate = g.Key,
                TotalAmount = g.Sum(t => t.Amount)
            }));

        _transactions = TransactionViewModel.Transactions;
    }
}

ChartDataModel

public class ChartDataModel : ViewModelBase
{
    public double TotalAmount { get; set; }
    public DateTime ProcessDate { get; set; }

    public ChartDataModel(DateTime processDate, double totalAmount)
    {
        ProcessDate = processDate;
        TotalAmount = totalAmount;
    }
}

This is the error that I am getting:

"There is no argument given that corresponds to the required parameter 'processDate' of 'ChartDataModel.ChartDataModel(DateTime, double)'."

What I'd like to do is use this Transaction in the SpendingSummaryViewModel so I can bind it in the UI to show it in a chart.


Solution

  • You are getting this error because your ChartDataModel don't have a constructor without parameters.

    On SpendingSummaryViewModel change the creation of ChartDataModel to

    (...)
    .Select(g => new ChartDataModel(g.Key, g.Sum(t => t.Amount)))
    (...)
    

    Or add a constructor without parameters in the ChartDataModel class.