理想情况下,您希望一次将所有相关记录检索到内存集合中,然后在递归期间从该内存集合中读取。记录的记忆/缓存范例将简化这一过程,并将业务逻辑与数据访问逻辑分开。
首先,创建一个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;
}
这是一个解决方案的粗略想法,可能需要一些调整和试验才能使一切正常。
表格有多大?您可以使用MenuParent键一次将表读入Dictionary>。 –
Paparazzi
@Blam它很小,不到50行。 – Maysam
为什么不使用递归** SQL **在单个语句中检索此信息。 –