私はAccountGroup
自己参照エンティティである を持っています。リーフAccountGroup
には 1 つ以上の を含めることができますAccounts
。どちらのエンティティにもBalance
プロパティがあります。それぞれAccountGroup
に、サブグループの の合計、またはBalance
すべてのアカウントの の合計 (リーフ グループの場合) があります。Balance
Balance
AccountGroup
すべての とのツリー リストを作成するAccount
には、このオブジェクト グラフを再帰的にトラバースする必要があります。これにより、DB への呼び出しが大量に発生します。
DB 呼び出しの数を減らすようにこれを改善する方法はありますか?
ありがとう
ここにトリミングされたコードがあります
アカウント (1 つの AccountGroup のみに属します)
public class Account
{
public int Id { get; set; }
public int GroupId { get; set; }
public string Name { get; set; }
public decimal Balance { get; set; }
public string AccountType { get; set; }
public virtual AccountGroup Group { get; set; }
}
AccountGroup (0 個または多数の AccountGroups を持ち、リーフの場合は 1 個以上の Accounts を持ちます)
public class AccountGroup
{
public AccountGroup()
{
Accounts = new HashSet<Account>();
Groups = new HashSet<AccountGroup>();
}
public int Id { get; set; }
public bool IsRoot { get { return Parent == null; } }
public bool IsLeaf { get { return !Groups.Any(); } }
public decimal Balance { get { return IsLeaf ? Accounts.Sum(a => a.Balance) : Groups.Sum(g => g.Balance); } } // if leaf group, get sum of all account balances, otherwise get sum of all subgroups
public int? ParentId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ISet<Account> Accounts { get; private set; }
public virtual ISet<AccountGroup> Groups { get; private set; }
public virtual AccountGroup Parent { get; set; }
}
呼び出しコード
// start processing root groups (ones without parent)
foreach (var rootGroup in db.AccountGroups.Include(g=>g.Groups).Where(g => g.ParentId == null))
{
TraverseAccountGroup(rootGroup, 0);
}
// recursive method
private static void TraverseAccountGroup(AccountGroup accountGroup, int level)
{
//
// process account group
//
Console.WriteLine("{0}{1} ({2})", String.Empty.PadRight(level * 2, '.'), accountGroup.Name, level);
//
// if subgroups exist, process recursivelly
//
if (accountGroup.Groups.Any())
{
foreach (var subGroup in accountGroup.Groups)
{
TraverseAccountGroup(subGroup, level + 1);
}
}
//
// otherwise, process accounts belonging to leaf subgroup
//
else
{
foreach (var account in accountGroup.Accounts)
{
Console.WriteLine("ACCOUNT [{0}]", account.Name);
}
}
}