Blog Moved ....

ScottCate.com

community

frenz

my book(s)

my products

February 2004 - Posts

String Concatenation Speed?

Is there any hard research about which one of the following is faster, or more scalable?

  1. string name = “Scott“ + “ “ + “Cate“;
  2. StingBuilder sb = new StringBuilder();
    sb.Append(“Scott“);
    sb.Append(“ “);
    sb.Append(“Cate“);
    string name = sb.ToString();
  3. string name = string.Format(“{0} {1}“,“Scott“,“Cate“)
  4. string name = string.Concat("Scott"," ","Cate");

Maybe even another way that I'm not aware of yet?

Timed Execution Pages in Whidbey?

Does anyone know if Whidbey has an elegant way of executing pages on a schedule? I'm hoping for something in the web.config. Maybe something like <ScheduledExecution> with the ability to list a page to fire, and a schedule to fire it.

This would be much more elegant then the current hacks. Seems to solve the problem fro hosted users in an ISP environment, that don't have access to server resources.

HttpContext.Cache Viewer (With DataSet Support)

Aw, the HttpContext.Cache. Most of the items I place in the Cache are named with GUID's so it's not very helpful to loop through and print out the Cache Item Name. I've built this handy ASPX page that gives a nice little view of the Cache in human readable form. All the Datasets, are displayed, including the DataTables. now keep in mind, that I'm not worried about the graphic design, or the looks here, I just wanted to make something work. I did add a little javascript to expand/collapse the items since they tend to be rather large.

I'm happy to answer questions, and I'm eager for advice, on a better way, faster way, or just general feedback on the code.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >

<script language="javascript">
<!--
function OpenOrCloseSpan(spanTag)
{
var st = document.getElementById( spanTag );
if ( st.style.display == 'none' )
st.style.display = '';
else
st.style.display = 'none';
}
// -->
</script>
<HTML>
<HEAD>
<title>Display Cache Keys And Values</title>
</HEAD>
<body>
<a href="DisplayCacheKeyValues.aspx">Refresh Page</a>
<form id="Form1" method="post" runat="server">
<asp:PlaceHolder ID="phTable" Runat="server" />
</form>
</body>
</HTML>
protected System.Web.UI.WebControls.PlaceHolder phTable;


private void Page_Load(object sender, System.EventArgs e)
{
if(!Page.IsPostBack)
{
GetAndDisplayCacheItems();
}
else
{
//These have to be bound to fire the event. This method
//Bind the link buttons, but without the rest of the over head
CreateAndBindRemoveButtons();
}
}

private void GetAndDisplayCacheItems()
{
//this stringbuilder gets used throughout the method as needed.
StringBuilder sb = new StringBuilder();

//Grab the context item, for reference so it has local scope to
//save having to get walk back and get the Context item
HttpContext ctx = HttpContext.Current;
IDictionaryEnumerator d = ctx.Cache.GetEnumerator();
while(d.MoveNext())
{
// Create HTML table for display of each item in cache
HtmlTable t = new HtmlTable();
//Set General Table Properties
t.BorderColor = "FF0000";
t.CellPadding = 10;
t.CellSpacing = 0;
t.Border = 1;

HtmlTableRow r = new HtmlTableRow();
HtmlTableCell CacheKeyTableCell = new HtmlTableCell();
CacheKeyTableCell.VAlign = "top";

//Clear the stringbuilder and add the CachItem Type and value
sb.Length = 0;
sb.Append("<B>Cache Item Type: </B>");
sb.Append(ctx.Cache[d.Key.ToString()].GetType().ToString());
sb.Append("<BR /><B>Value: </B><BR />");
sb.Append(Server.HtmlEncode(d.Value.ToString()));

//Add the Item Type
CacheKeyTableCell.Controls.Add(new LiteralControl(sb.ToString()));
r.Cells.Add(CacheKeyTableCell);

HtmlTableCell CacheValueTableCell = new HtmlTableCell();
switch(d.Value.ToString())
{
//This is the fun code, that turns dataset tables,
//into HTML Tables
case "System.Data.DataSet" :
//Coutner to Create a label
int tblCounter = 0;
//Create a new dataset to be used as a copy of the cached dataset
//We do this, becuase some of the values get manipulated and we
//don't want to chagne the actual values.
DataSet ds = new DataSet();
//Get copy of dataset from Cache
ds = ((DataSet)ctx.Cache[d.Key.ToString()]).Copy();
//Iterate throguht the tables in the dataset
foreach(DataTable dt in ds.Tables)
{
//Set flag to see if the table has rows.
//We won't add empty tables to the view
bool rowsProcessed = false;
foreach(DataRow dr in dt.Rows )
{
//Found rows, set flag to true
rowsProcessed = true;
//loop through each colomn int he DataRow and convert
//any text, to HTML text. A lot of cached data, is data that
//gets rendered as XML, or HTML, so this makes the data human
//readable. This is the reason for working with a copy of the
//dataset, and not the real cached item.
for(int x = 0; x < dr.ItemArray.GetLength(0); x++)
{
//This is my sloppy way to catch nulls, and any other
//conversion errors.
try
{
string columnData = Server.HtmlEncode(dr[x].ToString());
dr[x] = columnData;
}
catch {}
}
}
//Add populated tables to ValueTableCell, via
//new datagrid.AutoGenerateColumns
if(rowsProcessed)
{
//Add Seperation bar between Tables
if(tblCounter > 0)
{
CacheValueTableCell.Controls.Add(new LiteralControl("<HR>"));
}
DataGrid dg = new DataGrid();
dg.GridLines = GridLines.Both;
dg.AutoGenerateColumns = true;
dg.BorderColor = Color.Black;
dg.BorderWidth = Unit.Pixel(2);
dg.DataSource = dt;
dg.DataBind();
//Set some styles on the columns for readability
foreach(DataGridColumn c in dg.Columns)
{
c.ItemStyle.HorizontalAlign = HorizontalAlign.Left;
c.ItemStyle.VerticalAlign = VerticalAlign.Top;
}
//Add a Table Counter Label
sb.Length = 0;
sb.Append("DataTable ");
sb.Append(tblCounter.ToString());
sb.Append("<BR />");
CacheValueTableCell.Controls.Add(new LiteralControl(sb.ToString()));
CacheValueTableCell.Controls.Add(dg);
}
tblCounter++;
}
r.Cells.Add(CacheValueTableCell);
break;
default :
break;
}
//Add the row to the HTML table
t.Rows.Add(r);

//Start <P> Tag
phTable.Controls.Add(new LiteralControl("<P>"));

//Create and add Remove Link Button
phTable.Controls.Add(CreateRemoveLinkButton(d.Key.ToString()));

//Add a spacer between the remove link button and the open/close javascript
phTable.Controls.Add(new LiteralControl("&nbsp;"));

//Create and add the anchor tag to open/close javascript
HtmlAnchor a = new HtmlAnchor();
a.HRef= "Javascript:OpenOrCloseSpan('Span_" + d.Key.ToString() + "')";
a.Controls.Add(new LiteralControl("Open/Close"));
phTable.Controls.Add(a);

//Create and add the Name of the Cache Item (preeceded with a space)
StringBuilder CacheItemDisplayName = new StringBuilder();
CacheItemDisplayName.Append("&nbsp;");
CacheItemDisplayName.Append(d.Key.ToString());

//Add the Open Span Tag and ID for javascript to open and close
CacheItemDisplayName.Append("<span id=\"span_");
CacheItemDisplayName.Append(d.Key.ToString());
CacheItemDisplayName.Append("\" style=\"Display: None\">");
phTable.Controls.Add(new LiteralControl(CacheItemDisplayName.ToString()));

//Add the data table to the placeholder
phTable.Controls.Add(t);
//Add the closing Span and P tags.
phTable.Controls.Add(new LiteralControl("</span></P>"));
}
}

private LinkButton CreateRemoveLinkButton(string buttonID)
{
LinkButton RemoveLinkButton = new LinkButton();
RemoveLinkButton.Text = "Remove";
//Set the ID of the LinkButton to the Cache Key Name.
//This is going to be used in the eventhandler, to remove item from cache
RemoveLinkButton.ID = buttonID;
//Wire up event
RemoveLinkButton.Click += new EventHandler(RemoveLinkButton_Click);
return RemoveLinkButton;
}

private void CreateAndBindRemoveButtons()
{
HttpContext ctx = HttpContext.Current;
IDictionaryEnumerator d = ctx.Cache.GetEnumerator();
while(d.MoveNext())
{
phTable.Controls.Add(CreateRemoveLinkButton(d.Key.ToString()));
}
}

private void RemoveLinkButton_Click(object sender, EventArgs e)
{
HttpContext ctx = HttpContext.Current;
//Cast sender as LinkButton and Check if still in cache
if(ctx.Cache[((LinkButton)sender).ID] != null)
{
//Remove item from Cache
ctx.Cache.Remove(((LinkButton)sender).ID);
}
phTable.Controls.Clear();
GetAndDisplayCacheItems();
}

#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: This call is required by the ASP.NET Web Form Designer.
//
InitializeComponent();
base.OnInit(e);
}

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion

More Posts