|
|
Comments and Discussions
|
|
 |

|
I saw a class for sqlite, and I tried it , but there seems a lot problems of it. It loos like that your sql sentence is for sql server but not sqlite. Or maybe I did something wrong. Can you tell me how to use it for sqlite?
|
|
|
|

|
Really Very Very Marvellous Coding, and follow the structure. Thanks for Co-operation in this regard.
Wasiuddin Siddiqui
|
|
|
|

|
Great code.
Are you going to add the method for adding and removing nodes?
Please post an example of adding a node, and removing a node, I assume a partial rebuild will be required for these operation.
Many Thanks!
|
|
|
|
|

|
be carefull of using it with big data. The big goal is, that you can find the data you
need in a very short time, but insert or delete data will need a lot of time.
I used it in a own system and i had terrible insert-times after 5000 rows.
But normally, for small systems it is a nice and mid easy technique
|
|
|
|

|
Dear Sir,
I am making the project in C# for showing "Hierarchical Data". As my need, i want to add/delete node at any level with the using of simple UI. According to our requirements, the number of nodes may be in the range of 50,00,000 to 60,00,000. Can I use your code in terms of performance & efficiency?
Can your code gives good result if node range goes to 50,00,000 to 60,00,000.
Please suggest us.
With Regards
Ashutosh
ashutosh.sgupta@yahoo.co.in
ashu_s_g@yahoo.co.in
|
|
|
|

|
Unfortunately, this version of the code is not optimized, but I have a recent version "not uploaded yet" that is optimized for high performance, according to my busy schedule, I could upload the new version with in three weeks, but I think the following code may help you for time beings, you may need also to enhance this portion of the code by using parameterized query and removing un-wanted fields.
//Insert Single Node Directly To Tree -->
public override int AddAndUpdateNode(MpttTreeNode node)
{
if (!InternalBeginUpdate())
return -1;
if (node.ID > 0)
{//Updateing existing one, don't update left, right or parent fields
SqlCommand cmd = new SqlCommand(string.Format(@"
UPDATE
{0} SET Title=@Title, unitID=@unitID ,divID=@divID, LeafID=@LeafID, defaultContent=@defaultContent
WHERE
ID=@ID", ContentTableName), con);
cmd.Parameters.AddWithValue("@Title", node.Title);
cmd.Parameters.AddWithValue("@unitID", node.UnitID);
cmd.Parameters.AddWithValue("@divID", node.DivID);
cmd.Parameters.AddWithValue("@defaultContent", node.ContentType);
cmd.Parameters.AddWithValue("@LeafID", node.LeafID);
cmd.Parameters.AddWithValue("@ID", node.ID);
ExecuteNonQuery(cmd);
}
else
{//Adding new one
// Get parent of the new node
MpttTreeNode parent = GetNodeByID(node.ParentID);
int nextleafID = GetNextLeafID();
//Output, provides you access to inserted and deleted logical tables.
// ....... BUT ............
//there is a limitation, where you have no choice than to use a workaround of "scope_identity"
//The limitation is: you cannot using OUTPUT without INTO for table which has triggers
//DML "Data Manipulation Language", puts this restriction
//SET NOCOUNT ON insert into MyTable values(...) select scope_identity() as id
//........................
//Output, provides you access to inserted and deleted logical tables.
SqlCommand cmd = new SqlCommand(string.Format(@"
DECLARE @MyTableVar table( ID int);
INSERT INTO
{0} (parentID,Title,lft,rgt,leafID,isLeaf,unitID,divID,defaultContent)
OUTPUT INSERTED.ID INTO @MyTableVar
VALUES
(@ParentID,@Title,@Left,@Right,@LeafID,@IsLeaf,@UnitID,@DivID,@defaultContent);
SELECT ID FROM @MyTableVar;", ContentTableName), con);
//cmd.CommandType = CommandType.TableDirect;
cmd.Parameters.AddWithValue("@Title", node.Title);
cmd.Parameters.AddWithValue("@ParentID", node.ParentID);
node.Left = (parent==null ? 1:parent.Right); // node left equals parent node right
cmd.Parameters.AddWithValue("@Left", node.Left);
node.Right = node.Left + 1; // node right equals node left + 1
cmd.Parameters.AddWithValue("@Right", node.Right);
cmd.Parameters.AddWithValue("@LeafID", nextleafID);
cmd.Parameters.AddWithValue("@IsLeaf", node.IsLeaf);
cmd.Parameters.AddWithValue("@UnitID", node.UnitID);
cmd.Parameters.AddWithValue("@DivID", node.DivID);
cmd.Parameters.AddWithValue("@defaultContent", node.ContentType);
//Object obj = ExecuteScalar(cmd);
node.ID = (int)ExecuteScalar(cmd);
node.LeafID = nextleafID;
//Update Nodes With Rights greater than my node right
cmd = new SqlCommand(string.Format(@"update {0} set lft=lft+2 , rgt=rgt+2 WHERE lft>{1} AND rgt>{1}", ContentTableName, node.Right), con);
ExecuteNonQuery(cmd);
//Update Bread Crump Nodes
cmd = new SqlCommand(string.Format(@"update {0} set rgt=rgt+2 WHERE (lft<{1} AND rgt>={2}) or (id={3})", ContentTableName, node.Left, node.Right, node.ParentID), con);
ExecuteNonQuery(cmd);
}
InternalEndUpdate();
//return the ID of the inserted record
return node.ID;//
}
//Delete Node With its Children
public override void DeleteNode(int id)
{
if (!InternalBeginUpdate())
return;
SqlCommand cmd = new SqlCommand(string.Format("SELECT * FROM {0} WHERE ID={1}", ContentTableName, id), con);
List<MpttTreeNode> nodes = GetNodeCollectionFromReader(ExecuteReader(cmd));
if (nodes.Count > 0)
{
MpttTreeNode node = nodes[0];
int ChildernCount = (node.Right - node.Left -1)/2;
int Difference = 2*(1+ChildernCount);
// Delete Node and its Children
cmd.CommandText = string.Format("DELETE FROM {0} WHERE (ID={1}) or (ParentID = {1})", ContentTableName, id);
ExecuteNonQuery(cmd);
// update Nodes after this deleted node
cmd.CommandText = string.Format("UPDATE {0} SET lft=lft-{1}, rgt=rgt-{1} WHERE lft>{2} AND rgt>{2}", ContentTableName,Difference, node.Right);
ExecuteNonQuery(cmd);
// update breadcrump nodes
cmd.CommandText = string.Format("UPDATE {0} SET rgt=rgt-{1} WHERE (lft<{2} AND rgt>={3}) or (id={4})", ContentTableName, Difference, node.Left, node.Right, node.ParentID);
ExecuteNonQuery(cmd);
}
InternalEndUpdate();
}
public override List<MpttTreeNode> GetSiblings(int nodeID)
{
if (!InternalBeginUpdate())
return null;
SqlCommand cmd = new SqlCommand(string.Format("SELECT * FROM {0} WHERE ID={1}", ContentTableName, nodeID), con);
List<MpttTreeNode> nodes = GetNodeCollectionFromReader(ExecuteReader(cmd));
List<MpttTreeNode> list = null;
if (nodes.Count > 0)
{
MpttTreeNode node = nodes[0];
cmd.CommandText = string.Format("SELECT * FROM {0} WHERE parentID={1} and NOT ID={2}", ContentTableName, node.ParentID, node.ID);
list = GetNodeCollectionFromReader(ExecuteReader(cmd));
}
else
list = null;
InternalEndUpdate();
return list;
}
// Get BreadCrump nods // Parent nodes // Parent Nodes Path //
public override List<MpttTreeNode> GetBreadCrump(int nodeID)
{
if (!InternalBeginUpdate())
return null;
MpttTreeNode node = GetNodeByID(nodeID);
SqlCommand cmd = new SqlCommand(string.Format("SELECT * FROM {0} WHERE lft<{1} and rgt>{2} Order By ParentID", ContentTableName, node.Left,node.Right), con);
List<MpttTreeNode> nodes = GetNodeCollectionFromReader(ExecuteReader(cmd));
InternalEndUpdate();
return nodes;
}
//-----------------------------------
// Move node with children to other parent // drag drop tree nodes
public override void MoveNode(MpttTreeNode child, MpttTreeNode newParent)//int nodeID , int newParentID)
{
//Case of: child is the root of the tree
if (child.ParentID == 0)
return;
//Get the root in order for future rebuild after updating
List<MpttTreeNode> parentBreadCrumbs = GetBreadCrump(newParent.ID);
if (parentBreadCrumbs.Count <= 0)
return;
MpttTreeNode rootNode = parentBreadCrumbs[0];
//Check conflict
parentBreadCrumbs.Reverse();//make parents before childs
foreach (MpttTreeNode bcNode in parentBreadCrumbs)
{
//Case of conflict: if moved node go to be a child of one of its children
if (bcNode.ID == child.ID)
return;
}
//Update and rebuild all
if (!InternalBeginUpdate())
return;
//
SqlCommand cmd = new SqlCommand(string.Format("UPDATE {0} SET ParentID={1} WHERE ID={2}",
ContentTableName, newParent.ID,child.ID), con);
ExecuteNonQuery(cmd);
RebuildTree(rootNode.ID, 1);
//
InternalEndUpdate();
}
public MpttTreeNode GetRootNode(int nodeID)
{
if (!InternalBeginUpdate())
return null;
MpttTreeNode rootNode = null;
MpttTreeNode Mynode = GetNodeByID(nodeID);
if (Mynode.ParentID == 0)
return Mynode;
List<MpttTreeNode> nodes = GetBreadCrump(nodeID);
nodes.Reverse();
foreach (MpttTreeNode node in nodes)
{
if (node.ParentID == 0)
{
rootNode = GetNodeByID(node.ID);
break;
}
}
return rootNode;
}
|
|
|
|

|
Hi,
I could not find a solution file for tree view project.
Does this work on visual studio 2005?
thanks
Asanka
|
|
|
|

|
It is created on VS2008, but the entire classes could be easily reused and separated, you could create a new solution on 2005 and import .cs files.
|
|
|
|

|
hi,
your e.g. is great. but i'm searching for a solution with hierarchyid. i would write SP's in sql server 2008 and use them in my allplication code (c#). would you give me an e.g.
thx
majid rezaei
|
|
|
|

|
I don't understand what do you ask me to provide?, could you please clear more the meaning of your statement "give me an e.g".
What is HierarchyID? Is it another approach defer than MPTT?
|
|
|
|

|
HierarchID is a new data type of SQL SERVER 2008 for storing of hierarchical data. --> http://technet.microsoft.com/en-us/library/bb677290.aspx. I thought and hoped, that you know this data type. I'm searching for a solution to generate a tree by using of hierarchyid approach.
|
|
|
|

|
Hello Sir.I'm Vijay. I read ur Source code abt modified preorder tree traversal.
Its GREAT.
But I'm facing some problems in that "MpttCoreEngine.cs" form.
Would u plz send me some extra reading material for that code so that I can easiely understand that form???
I would be most greatful if You would do the same.
My email Id is "vijay_bhavsar15@yahoo.co.in"
good day Sir.
|
|
|
|

|
Dear Vijay,
For more information about MPTT technique, Please, read this simple article for "Gijs Van Tulder".
Storing Hierarchical Data in a Database[^]
However, I'll try to explain MPTT more in the future.
Regards
Wael AlGhool
|
|
|
|

|
Hierarchical tree...!
i like this code...!
Thank man...!
|
|
|
|

|
Well I've just finished to read the DrawTree. I was interested in drawing the image. I have to say is very well written, clear and full of useful comments. You put a lot of work into this. It was really a pleasure to read that function.
Dr.Luiji
Trust and you'll be trusted.
Try iPhone UI [ ^] a new fresh face for your Windows Mobile, here on Code Project.
|
|
|
|

|
Hope it is useful.
What do you think if I go to explain that algorithm in a separate article? is it worth to do that?
|
|
|
|

|
Wael Alghool wrote: What do you think if I go to explain that algorithm in a separate article?
The MpttCoreEngine is a good reading material, with a lot graphics, lambada and math.
I like it. At least you can add the save and load.
Wael Alghool wrote: is it worth to do that?
Depends, It's a Bitmap of a TreeNode. Probably a section about that here, can be more helpful and it add more power to the article .
Kind regards
Dr.Luiji
Trust and you'll be trusted.
Try iPhone UI [ ^] a new fresh face for your Windows Mobile, here on Code Project.
|
|
|
|

|
Hello Sir.I'm Vijay. I read ur Source code abt modified preorder tree traversal.
Its GREAT.
But I'm facing some problems in that "MpttCoreEngine.cs" form.
Would u plz send me some extra reading material for that code so that I can easiely understand that form???
I would be most greatful if You would do the same.
My email Id is "vijay_bhavsar15@yahoo.co.in"
good day Sir.
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
|
Gathering of various algorithms into one library to transform Hierarchical trees between various formats, and allows them to be represented into SQL2005, the formats supported are TreeView, Textual, Tabular, Modified Preorder Tree Traversal and Graphical.
| Type | Article |
| Licence | CPOL |
| First Posted | 10 Dec 2008 |
| Views | 47,474 |
| Downloads | 1,345 |
| Bookmarked | 82 times |
|
|