0

I am working in C#, winform and Mysql. (Visual Studio 2010).

In my project all menustrip items are invisable. At the login time its visible which menustrip item user rights. For that i invisible all menu strip,. And I code for visible the menustrip items.

But its take too much time. more then 5 minutes. So I have Few Questions.

  1. How I find this coding execution time?. (My Code Below)....
  2. Is any special tool is there?.
  3. How to Reduce the time with effective code?
  private void menuActive(ToolStripItemCollection items)
        {
            hp.getConnStr();
            MySqlConnection connection = new MySqlConnection(hp.myConnStr);
            MySqlCommand command = connection.CreateCommand();
            MySqlDataReader Reader;
            command.CommandText = "select menu_key from mcs_menu_rights where userid ='"+userId+"'";
            connection.Open();
            Reader = command.ExecuteReader();
            while (Reader.Read())
            {
                foreach (ToolStripMenuItem item in items)
                {
                    if (item.Name == Reader[0].ToString())
                    {
                        item.Visible = true;
                    }
                    else
                    {
                        menuActive(item.DropDown.Items);
                    }
                }
            }
            connection.Close();
        }
4
  • One way to do this is to use a tool called a profiler. There are many available for .NET. Commented Feb 7, 2012 at 13:47
  • 2
    should this code even work? You are recursively calling the function while the SqlDataReader is still open... Commented Feb 7, 2012 at 13:49
  • @zach, he creates multiple readers and connections, if the sql server supports multiple connections it'll work just fine. Commented Feb 7, 2012 at 13:54
  • @ZachGreen might work if MARS is enabled Commented Feb 7, 2012 at 13:54

7 Answers 7

3

You could profile, but there are some definite improvements I can see straight off:

Seperate out your recusive function away from the database query. This way you query the database once. Note that it's not doing exactly the same, but I'm not sure what that table looks like so you'll have to test it.

private void menuActive(ToolStripItemCollection items) 
    { 
        hp.getConnStr(); 
        MySqlConnection connection = new MySqlConnection(hp.myConnStr); 
        MySqlCommand command = connection.CreateCommand(); 
        MySqlDataReader Reader; 
        command.CommandText = "select menu_key from mcs_menu_rights where userid ='"+userId+"'"; 
        connection.Open(); 
        Reader = command.ExecuteReader(); 
        while (Reader.Read()) 
        {
            var nameFromDB = Reader[0].ToString();
            setMenuActiveByName(items, nameFromDB);
        }
        connection.Close(); 
    }

    //This is the recursive bit, but doesn't re-enquire the database
    private void setMenuActiveByName(ToolStripItemCollection items, string name) 
    {
            foreach (ToolStripMenuItem item in items) 
            { 
                if (item.Name == name) 
                { 
                    item.Visible = true; 
                } 
                else 
                {
                    setMenuActiveByName(item.DropDown.Items, name); 
                } 
            }
    } 
Sign up to request clarification or add additional context in comments.

Comments

1

Yes, creating a dbase connection for every single menu item is going to take a while. You'll need to avoid calling MenuActive() inside the foreach loop. Make it smarter with a little helper method:

    private static bool EnableMenuItem(ToolStripItemCollection items, string name) {
        foreach (ToolStripMenuItem item in items) {
            if (item.Name == name) {
                item.Visible = true;
                return true;
            }
            else if (item.DropDown.Items.Count > 0 {
                if (EnableMenuItem(item.DropDown.Items, name)) return true;
            }
        }
        return false;
    }

And call it like this:

        ...
        while (Reader.Read()) 
        { 
            EnableMenuItem(items, Reader[0].ToString();
        }

Comments

1

Question 1 and 2

var time = TimeAction(() =>
    {
        //CODE here
    });

private static TimeSpan TimeAction(Action action)
{
    var sw = new Stopwatch();
    sw.Start();
    action.Invoke();
    sw.Stop();
    return sw.Elapsed;
}

Question 3

//One loop through all records in database
while (Reader.Read())
{
    //Another loop through all the control
    foreach (ToolStripMenuItem item in items)
    {
        if (item.Name == Reader[0].ToString())
        {
            item.Visible = true;
        }
        else
        {
            menuActive(item.DropDown.Items);
        }
    }
}

Given you have 1000 records in a database and 10 items, this take 10 000 iterations, each including trip to database to serve new data.

Comments

0

Use the StopWatch class to time the execution, http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.aspx. Log the time after each step to determine what is taking so long.

Comments

0

You can use the StopWatch class for testing performance

StopWatch sWatch = new StopWatch();
sWatch.Start();
// Code comes here
...
sWatch.Stop();
// sWatch.Elapsed // Contains the time interval

It seems like you have a bad recursion there - you run the function on the same collection over and over.

Comments

0

Depending on your version of VS, you might be able to use the builtin profiling tools to find where the time is spent.

Comments

0

For questions 1 and 2, you can use stopwatch:

Stopwatch watch = new Stopwatch();

watch.Start();
//YOUR CODE HERE
watch.Stop();

Console.WriteLine("Elapsed: {0}",watch.Elapsed);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.