I would like to create a simple general ledger app in c# 6 and entity framework 6 but I guess I am struggling with the proper design.
From my (simplified) point of view a general ledger is a collection of transactions which later can be used to compile relevant data/reports out of.
My requirements regarding the transactions are:
Here is what I have come up with so far:
public class GeneralLedger
{
public int GeneralLedgerId { get; set; }
public DateTime FiscalPeriodStartDate { get; set; }
public DateTime FiscalPeriodEndDate { get; set; }
private ICollection<GeneralLedgerTransaction> _transactions;
public ICollection<GeneralLedgerTransaction> Transactions {
get
{
if (this._transactions != null) {
return this._transactions.ToList().AsReadOnly();
}
else
{
return null;
}
}
}
public void AddTransaction(GeneralLedgerTransaction trx)
{
if (trx.PostingDate < this.FiscalPeriodStartDate || trx.PostingDate > this.FiscalPeriodEndDate)
{
throw new ArgumentOutOfRangeException("invalid booking date");
}
else
{
this._transactions.Add(trx);
}
}
}
public class GeneralLedgerTransaction
{
public int GeneralLedgerTransactionId { get; set; }
public DateTime PostingDate { get; set; }
public virtual ICollection<GeneralLedgerTransactionLine> GeneralLedgerTransactionLines { get; set; }
}
public class GeneralLedgerTransactionLine
{
public int GeneralLedgerTransactionLineId { get; set; }
public int FinancialAccountId { get; set; }
public virtual FinancialAccount FinancialAccount { get; set; }
public int GeneralLedgerTransactionTypeId { get; set; }
public virtual GeneralLedgerTransactionType GeneralLedgerTransactionType { get; set; }
public decimal Amount { get; set; }
}
public class FinancialAccount
{
public int FinancialAccountId { get; set; }
public string Name { get; set; }
}
public class GeneralLedgerTransactionType
{
public int GeneralLedgerTransactionTypeId { get; set; }
public string Name { get; set; }
}
public class MyDbContext : DbContext
{
public DbSet<GeneralLedger> GeneralLedgers { get; set; }
public DbSet<GeneralLedgerTransaction> GeneralLedgerTransactions { get; set; }
public DbSet<GeneralLedgerTransactionLine> GeneralLedgerTransactionLines { get; set; }
public DbSet<FinancialAccount> FinancialAccounts { get; set; }
public DbSet<GeneralLedgerTransactionType> GeneralLedgerTransactionTypes { get; set; }
}
Now this works well in terms of no existing transaction can be removed or altered as the the Transaction
property returns a ReadOnly
-list and every new newly added transaction is checked against the date period rule. And I also can see that the records are saved to the database. So far so good, the only thing that I am currently missing is that existing records are not loaded to _transactions
.
What can I do to make existing transactions available in _transactions
without calling the entity framework from within the domain class? Or is there maybe a better way (i.e. a better design) to solve this problem?
After further investigation I learned that I can achieve what I was looking for as follows:
_transactions
from private
to protected virtual
modelBuilder.Configurations.Add(new GeneralLedger.GeneralLedgerTransactionsMapper());
to OnModelCreating
.
public class GeneralLedgerTransactionsMapper : EntityTypeConfiguration<GeneralLedger>
{
public GeneralLedgerTransactionsMapper()
{
HasMany(s => s._transactions);
}
}