理想的には、関連するすべてのレコードを一度にメモリ内コレクションに取得し、再帰中にそのメモリ コレクションから読み取る必要があります。レコードのメモ化/キャッシュのパラダイムにより、これが簡単になり、データ アクセス ロジックがビジネス ロジックから分離されます。
static
最初に、最初にデータベースからデータを取得するデータ取得メソッドを作成しますが、その後の呼び出しではメモリ内コレクションを利用します。を渡しているのでfTableName
、このメソッドは複数のテーブルで使用される場合と使用されない場合があるため、キャッシュは一度に複数のテーブルを格納でき (Dictionary
テーブル名のキーを使用)、異なるテーブルへのリクエストを個別に処理すると想定しています. (警告: テストされていないコードですが、アイデアが得られるはずです):
private static Dictionary<string, DataTable> _menuCache = null;
public static DataRow[] GetMenuLayer(string fTableName, string fID, string fClause)
{
if (_menuCache == null) _menuCache = new Dictionary<string, DataTable>();
if (!_menuCache.ContainsKey(fTableName)) {
// retrieve all records from the database the first time
SQLCommand = "SELECT * FROM " + fTableName;
...
_menuCache[fTableName] = result;
}
// query appropriate records from the cache
var dt = _menuCache[fTableName];
return dt.Select("MenuParent = " + fID + " AND Visible=1 AND " + fClause);
}
このメソッドはであるためstatic
、そのデータはリクエスト/レスポンス サイクル全体で保存されますが、レスポンス間では保存されません。したがって、これにより、メニューの生成が単一のデータベース呼び出しに削減されますが、ページがロードされるたびに、データは引き続き新しくロードされます。メニュー データが比較的静的である場合は、.NET キャッシュを使用して次のレベルに進むことができます。タイムアウトを指定すると、データベースの結果が保存されます (たとえば、一度に 30 分間更新する前)。その後、1 回のデータベース呼び出しだけでページを何度も読み込むことができます。
GenerateNestedMenus
データベースからデータを取得するコードは、代わりGetMenuLayer
に適切なパラメーターを使用して を呼び出します。次に、このメソッドは、可能な方法でデータを取得する責任があります (前者のメソッドは、取得方法を気にする必要はありません)。バックグラウンドで、テーブルが初めてfTableName
要求されると、テーブル全体がローカル メモリ キャッシュにダウンロードされます。次に、そのメモリ キャッシュは、パラメーターに従って後続の呼び出しでクエリされ、反復可能な結果行が返されます (これは、基本ロジックの非常に小さなサブセットしか理解できfClause
ないため、動的フィルター ロジックがそれほど複雑ではないことを前提としています)。dt.Select(
T-SQL
public string GenerateNestedMenus(string fTableName, string fID, string fClause)
{
DataRow[] dt = GetMenuLayer(fTableName, fID, fClause);
int i = 0;
string temp = null;
for (i = 0; i <= dt.Length - 1; i++) {
if (Convert.ToInt32(ChildCounter(fTableName, dt[i]["id"])) > 0) {
temp = "<li>" + Constants.vbCrLf + "<a href='#'>" + Strings.Trim(dt[i]["MenuName"]) + "</a>" + Constants.vbCrLf + Constants.vbTab + "<ul> ";
_temp += temp;
GenerateNestedMenus2("menus", dt[i]["id"], fClause);
_temp += Constants.vbTab + "</ul>" + Constants.vbCrLf + Constants.vbTab + "</li>" + Constants.vbCrLf;
} else {
//For rows they have not child
temp = Constants.vbTab + "<li><a href='#'>" + Strings.Trim(dt[i]["MenuName"]) + "</a>" + "</li>" + Constants.vbCrLf;
_temp += temp;
GenerateNestedMenus2("menus", dt[i]["id"], fClause);
}
}
return _temp;
}
これは解決策へのアプローチの大まかなアイデアであり、すべてを機能させるには微調整と実験が必要になる場合があります。