【发布时间】:2011-04-13 19:02:28
【问题描述】:
这个东西一开始并没有注意到它很慢,因为数据库中的“树节点”并不多。现在真的很慢,一看这有什么大问题吗?我真的需要对其进行优化,在我重新设计整个事情之前,我想知道是否有什么突出是真正的痛点。我已经将慢速部分缩小到递归存储库函数,这是这篇文章的最后一件事,但我必须定义一些导致它发生的事情......祝你好运。 (注意:这不是我写的,我只是进行了损坏控制,我正在努力解决它。)
首先要了解几点:
JsTreeNode 定义:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace App.Models
{
public class JsTreeNode
{
public JsTreeNode()
{
}
public Attributes attributes { get; set; }
public Data data { get; set; }
public string state { get; set; }
public List<JsTreeNode> children { get; set; }
}
public class Attributes
{
public string id { get; set; }
public string rel { get; set; }
public string mdata { get; set; }
public string href { get; set; }
public string complete { get; set; }
public string edit { get; set; }
public string title { get; set; }
public string resourceAccountID { get; set; }
}
public class Data
{
public string title {get;set;}
public string icon {get;set;}
}
}
现在是 TreeNodes 表定义:
CREATE TABLE [dbo].[TreeNodes](
[TreeNodeID] [int] IDENTITY(1,1) NOT NULL,
[TreeID] [int] NOT NULL,
[ParentNodeID] [int] NULL,
[ResourceID] [int] NULL,
[NodeOrder] [int] NOT NULL,
[NodeName] [nvarchar](250) NOT NULL,
[CreateBy] [int] NULL,
[CreateDate] [datetime] NULL,
[ModifyBy] [int] NULL,
[ModifyDate] [datetime] NULL,
[TreeRevisionID] [int] NULL,
树修订表定义...
CREATE TABLE [dbo].[TreeRevisions](
[TreeRevisionID] [int] IDENTITY(1,1) NOT NULL,
[TreeID] [int] NOT NULL,
[Notes] [text] NULL,
[CreatedBy] [int] NOT NULL,
[CreatedDate] [datetime] NOT NULL,
[ModifyBy] [int] NOT NULL,
[ModifyDate] [datetime] NOT NULL,
现在这里是 Get Action 本身,它需要 20-25 秒,您可以在那里看到它调用了我在此线程中进一步定义的存储库函数。
public ContentResult Get(string target,int id)
{
int revisionID = Convert.ToInt32(Request.QueryString["revisionID"]);
int tempUserID = (Request.QueryString["userID"] != null)
? Convert.ToInt32(Request.QueryString["userID"])
: UserID;
var nodesList = new List<JsTreeNode>();
if(target.Contains("tree"))
{
tree tree = _treeRepository.GettreeByID(id);
var cnode = new JsTreeNode
{
attributes = new Attributes {id = "0",title = tree.treeName},
data = new Data {title = tree.treeName},
children = _treeNodesRepository.GetNodesBytreeID(id, null,revisionID),
state = "open"
};
cnode.attributes.rel = "root";
cnode.attributes.mdata = "{draggable : true}";
nodesList.Add(cnode);
}
else
{
var trees = _CategoryRepository.getAlltreesByCategoryID(id);
IQueryable<tree> custom;
if(revisionID != 0)
{
custom = from c in trees
where
c.AccountID == AccountID
select c;
} else
{
custom = from c in trees
where
c.AccountID == AccountID && c.PublishedRevisionID != null && c.PublishedRevisionID != 0
select c;
}
var acme = from c in trees where c.AccountID == acmeContent.acmeID select c;
foreach (var tree in (custom.Count() > 0) ? custom : acme)
{
if(revisionID == 0 && tree.PublishedRevisionID == null) continue;
int tempRev = (revisionID != 0) ? revisionID : (int)tree.PublishedRevisionID;
if(custom.Count() == 1)
{
var tempNodes = _treeNodesRepository.GetNodesBytreeID(tree.treeID, null, tempUserID, tempRev);
nodesList.AddRange(tempNodes);
}
else
{
var cnode = new JsTreeNode();
cnode.attributes = new Attributes { id = tree.treeID.ToString(), title = tree.treeName };
cnode.data = new Data { title = tree.treeName };
cnode.children = _treeNodesRepository.GetNodesBytreeID(tree.treeID, null, tempUserID, tempRev);
cnode.attributes.rel = "Folder";
nodesList.Add(cnode);
}
}
}
var ser = new JavaScriptSerializer();
string res = ser.Serialize(nodesList);
return Content(res,"application/json");
}
...最后,“罪魁祸首”,看看它是如何称呼自己的:
public List<JsTreeNode> GetNodesByTreeID(int TreeID, int? parentID,int userID, int revisionID)
{
IQueryable<UserTreeNode> TreeNodes = GetAllTreeNodesByTreeIDAndParentNodeID(TreeID, parentID,userID,revisionID);
List<JsTreeNode> nodesList = new List<JsTreeNode>();
foreach (UserTreeNode node in TreeNodes)
{
string nodeName = node.Node.NodeName.Replace("'", "'");
JsTreeNode cnode = new JsTreeNode
{
attributes = new Attributes
{id = node.Node.TreeNodeID.ToString(),
title = nodeName},
data = new Data {title = nodeName}
};
if(node.Node.ResourceID != null)
{
cnode.attributes.complete = (node.IsComplete) ? "true" : "false";
cnode.attributes.rel = ResourceTypes.ReturnResourceTypeName(_resourceRepository.getResourceByID(Convert.ToInt32(node.Node.ResourceID)).ResourceTypeID);
cnode.attributes.href = "/resource/" + node.Node.ResourceID + "?minimal=true&nodeID=" + node.Node.TreeNodeID.ToString();
}
else
{
var nodeChildren = GetNodesByTreeID(TreeID, node.Node.TreeNodeID,userID,revisionID);
if (nodeChildren.Count > 0)
cnode.children = nodeChildren;
cnode.attributes.complete = "false";
cnode.attributes.rel = "Folder";
}
nodesList.Add(cnode);
}
return nodesList;
}
【问题讨论】:
-
omg 自动属性,认真的。
-
请详细说明,这是什么意思?我没有写这个,我只是被放在了损害控制上。 :)
-
不是答案,但是您是否使用 Profiler 来观察您的查询命中数据库?我敢打赌,您要么执行大量单独的查询,要么正在拖下大量数据。树数据结构可能会在短时间内变得非常庞大。
-
我怎样才能做 Profiler 的事情,也许可以给我链接一个教程?
-
@Shogun 自动属性:
public string OMG {get;set;}将其与您发布的代码中的任何单个属性进行比较。每个属性会使您的来源减少大约九行。
标签: c# asp.net-mvc linq-to-sql json recursion