理想情况下,您希望一次将所有相关记录检索到内存集合中,然后在递归期间从该内存集合中读取。记录的记忆/缓存范式将使这变得简单,并将您的数据访问逻辑与业务逻辑分开。
首先,创建一个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 分钟,然后刷新。然后页面可以加载多次,只需要一个数据库调用。
您从数据库中检索数据的代码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;
}
这是解决方案方法的粗略想法,可能需要进行一些调整和试验才能使一切正常。