.NET Performance Blog

April 28, 2006

Editable GridView with Add New/Insert button

Filed under: .NET,General — Eric P @ 6:05 pm

Please see the full post here:

http://www.entechsolutions.com/Blog/ViewPost.aspx?PostID=5 

ObjectDataSource: UpdateParameters ignored if DataObjectTypeName is used

Filed under: .NET,Bug Fix — Eric P @ 2:28 pm

If you specify 'DataObjectTypeName' parameter in ObjectDataSource — UpdateParameters get ignored. So if you have:

<asp:ObjectDataSource ID="objectDataSource" runat="server"

DataObjectTypeName="Customer" InsertMethod="Save"
UpdateMethod="Save"
DeleteMethod="Delete"
SelectMethod="LoadList"
TypeName="CustomerLogic">

<UpdateParameters>

<asp:Parameter Name="CategoryID" DefaultValue="5"/>

</UpdateParameters>

</asp:ObjectDataSource>

When you do update — parameter 'CategoryID' is not bind to Customer.CategoryID.

The solution to this problem is to add parameters dynamically in Updating event handler:

protected void objectDataSource_Updating(object sender, ObjectDataSourceMethodEventArgs e)

{

Customer customer=(Customer)e.InputParameters[0];

customer.CategoryID=5;

}

April 21, 2006

MSDN documentation is incorrect on using DataObjectTypeName with SelectMethod

Filed under: .NET — Eric P @ 6:39 pm

When reading MSDN documentation for ObjectDataSource.SelectMethod I found the following paragraph.

If the DataObjectTypeName property is set, the method is resolved in a different way. The ObjectDataSource looks for a method with the name that is specified in the SelectMethod property that takes one parameter of the type that is specified in the DataObjectTypeName property. In this case, the name of the parameter does not matter.

I tried it, but it doesn't look like it works. ObjectDataSource still looks for a method that has multiple SelectParameters arguements and not one 'DataObjectTypeName' arguement.

This is inconsistent with documentation for 'ObjectDataSource.DataObjectTypeName' where it says that:

Instead of specifying several parameters that are passed to the Update, Insert, and Delete methods, you can create one object that aggregates several data field values. This one object is passed to the methods, instead of several parameters.

Since my 'Select' method can have dozens of parameters I would rather use a class then dozens of arguements. I think the reason it works diferently from (Update/Insert/Delete) is that in some cases Search Arguements may be different from the ones required for Insert/Update/Delete. For example class Customer may have 'DateCreated', but CustomSearch will have 'DateCreatedFrom' and 'DateCreatedTo'.

The solution would be to provide another ObjectDataSource property 'SelectDataObjectTypeName' and hopefully MS can implement it for next update. For now they just need to fix up the documentation.

Life cycle of Custom Control within ASP.NET page

Filed under: General — Eric P @ 11:18 am

There are a lot of articles about life-cycle of the page and custom controls. The problem is they are all looked at separately. I had to do a bit of research on the order of control events within the events of the web page and I would like to share my findings.

To see what happens I created two items:

  • TestCustomControl.cs — custom composite control that gets included on Default.aspx. Adds a line to the log for the following events/methods:

OnInit

LoadViewState

OnLoad

CreateChildControls

SaveViewState

OnPreRender

Render

  • Default.aspx page — contains TestCustomControl and submit button. Adds line to the log for the following events:

Page_Init

Page_Load

Page_PreRender

Then I opened Default.aspx page. Here is the log of events:

Control: OnInit
Page: Page_Init
Page: Page_Load
Control: OnLoad
Page: Page_PreRender
Control: CreateChildControls
Control: PreRender
Control: SaveViewState
Control: Render

Looks pretty much what you expected. Here is what happens when I clicked on submit button:

Control: OnInit
Page: Page_Init
Control: LoadViewState
Control: CreateChildControls
Control: LoadPostData
Page: Page_Load
Control: OnLoad
Page: Page_PreRender
Control: PreRender
Control: SaveViewState
Control: Render

There are a couple of differences. LoadViewState and LoadPostData are now included in the cycle. The biggest difference (that has caused many headaches) is that 'CreateChildControls' now gets called before "Page_Load/OnLoad". Let's say you have a simple composite control that contains a text box and some other controls:

public class TextBoxPlus : CompositeControl
{

private TextBox _txt;

#region Class Properties

public string TextBoxValue
{

get {return (_txt.Text);}
set {_txt.Text=value;}

}

#endregion

protected override void CreateChildControls()
{

_txt = new TextBox();
_txt.ID = "txtTemp ";
_txt.CssClass = this.CssClass;
_txt.Columns = 3;
_txt.MaxLength = 3;

Controls.Add(_txt);

}

protected override void Render(HtmlTextWriter output)
{

}

}

The issue with CreateChildControls is that if you set 'TextBoxValue' property of the control in 'Page_Load' event of the page – you will get an exception that '_txt' doesn't exist. It does work without any problems if you set that value after the first form submit.

So:

protected void Page_Load(object sender, EventArgs e)

{

if (!this.isPostBack)

textBoxPlus.Value="SomeValue"; //Throws exception

else

textBoxPlus.Value="SomeValue"; //Works without any problems

}

To fix this problem modify TextBoxValue property as follows

public string Value
{

get
{

EnsureChildControls();

return _txt.Text;

}

set
{

EnsureChildControls();

_txt.Text=value;

}

}

EnsureChildControls() checks if CreateChildControls() has been called and if it hasn't — calls it.

April 12, 2006

Bug Fix: SELECT box displayed through Dynamic DIV in Internet Explorer

Filed under: Bug Fix — Eric P @ 9:05 am

There is a common bug that occurs when there is DIV (with absolute positioning) being displayed in front of SELECT html control. The SELECT control stays visible even with the div over it. It has to do with windowed controls (like SELECT) taking Z-Index precedence over any non-windowed control. The bug only occurs in Internet Explorer. To read more about it check out the following link

I create an example that contains both the bug and the fix at
this url.

The Fix
To fix the issue I basically create a new IFrame with the same dimensions and at the same position as Popup Div. Then I store IFrame object in a variable so I can destroy it when div is hidden.

Here is the complete code:

<script language="javascript">
<!–

var g_PopupIFrame;

function IsIE()
{

return ( navigator.appName=="Microsoft Internet Explorer" );

}

function HidePopupDiv(divID)
{

var divPopup;
divPopup=document.getElementById(divID);
divPopup.style.visibility = "hidden";

if (IsIE())
{

document.body.removeChild(g_PopupIFrame);
g_PopupIFrame=null;

}

}

function ShowPopupDiv(divID)
{

var divPopup=document.getElementById(divID);

if (!IsIE())
{

//Just display the div
divPopup.style.visibility ="visible";
return;

}

//Increase default zIndex of div by 1, so that DIV appears before IFrame
divPopup.style.zIndex=divPopup.style.zIndex+1;

var iFrame = document.createElement("IFRAME");
iFrame.setAttribute("src", "");

//Match IFrame position with divPopup
iFrame.style.position="absolute";
iFrame.style.left =divPopup.offsetLeft + 'px';
iFrame.style.top =divPopup.offsetTop + 'px';
iFrame.style.width =divPopup.offsetWidth + 'px';
iFrame.style.height =divPopup.offsetHeight + 'px';

document.body.appendChild(iFrame);

//Store iFrame in global variable, so it can get removed when divPopup is hidden g_PopupIFrame=iFrame;
divPopup.style.visibility ="visible";

}

//–>
</script>

Issue With SSL

There is an issue using IFrame with src="" on SSL pages. User will get a security warning whenever popup div is displayed and IFrame is created. Full description of the issue is here.

To work around this problem create an empty html page – "Blank.htm". Then replace line

iFrame.setAttribute("src", "");

with

iFrame.setAttribute("src", "/Blank.htm");

//Use correct absolute path for Blank.htm

April 10, 2006

Connection/Transaction scope

Filed under: XLib Framework — Eric P @ 12:57 pm

I have been doing some research on already available classes for keeping track of open transactions and connections. For .NET 2.0 Microsoft has released TransactionScope class which really simplifies keeping track of simple, nested and distributed transactions. It is very simple to use and MSDN documentation is pretty good. The only issue I found was that if you keep re-creating connection inside a transaction – the final transaction would be distributed which may result in performance loss.

Luckily one of the members of ADO.NET has countered the problem here:

http://blogs.msdn.com/dataaccess/archive/2006/02/14/532026.aspx

His class DbConnectionScope keeps track of already open connections and re-uses them within a TransactionScope. Following his lead I came up with two classes:

  • XOpenCnScope
  • XOpenCnTransScope (derived from XOpenCnScope)

These two classes allow me to open connection or connection & transaction scope using one statement. Internally open DbConnection and TransactionScope are re-used until all the nested Scopes have been closed.

Here is an example of open connection with transaction:

using (XOpenCnTransScope scope1 = new XOpenCnTransScope())

{

InsertRecord(1001);
InsertRecord(1002);

scope1.Complete();

}

public void InsertRecord(int recID)

{

XCommand cmd = new XCommand();

string sql = "INSERT INTO Db.Sample_XOpenCnTransScope (ID, Name) VALUES (" + customerID + ", '" + "Name_" + recID + " ')";

cmd.ExecuteSql(sql);

}
XCommand object is aware of XOpenCnScope and XOpenCnTransScope (similar of how TransactionScope is aware of DbConnection.Open). So when XCommand executes a query it will use the connection with transaction provided by OpenCnTransScope.

Actually if you create a new XCommand outside of OpenCnScope – it will automatically open default application connection – execute the query and close connection. That saves 4-5 lines of code.

April 6, 2006

Database Access Layer

Filed under: XLib Framework — Eric P @ 3:21 pm

Using XLib framework I would like to build web applications consisting of the following Tiers:

Database Access

Business Logic

Presentation

In this post I will talk about Database Access layer of XLib. There are a couple of things that I tried to accomplish:

  1. Automatically convert Database values into INullable datatypes. Handle DBNull.
  2. Hide complexities of DataSet, DataAdapter, etc…
  3. Build queries using OOP

Dilemmas I had to face:

1. Should I use Typed DataSet for Data Access?

I have tried the new DAL generation tools in VS 2005. It is very quick to generate a DAL over one database table. It also automatically converts DB data types into INullables. But there were a couple of issues that I could not figure out how to do:

  • The <<Item>>Row object (ex. CustomerRow) doesn't use Nullable types for properties. So how do I set CustomerRow.Age to null? Before I would use a NIL constant (like -1), but with INullables I would rather not use that. The weird part is that .Insert() and .Update() methods of CustomerTableAdapter take INullable types.
  • Generator creates 3 classes: Customer, CustomerRow & CustomerTableAdapter. It makes it a little more complex than it needs to be.
  • If I want to load some lookup values (for example CustomerType Lookup name) and use inner join in query to generate typed DataSet — the generator would not automatically create UPDATE, INSERT, DELETE. It only works if data is loaded from one table. I could always add GetCustomerTypeName() method to Customer partial class, but I would like to be able to load all info using one query.

For now I will fore-go TypedDataSet, but it is a lot better then in .NET version 1.1.

2. Should I use ANSI convention or SQL-86 (tables are separated from joins) for query building.

I have been using SQL-86 for most of my query writing and used ANSI whenever OUTER JOINS would get too complex. At this point I would like to start using ANSI for most of the new queires. One reason is Microsoft seems to be trying to phase SQL-86 out. The other is that queries are a little cleaner in ANSI format.

For now, I have decided to support both formats .

3. For transaction handling should I use TransactionScope?

This one I researched for a while. The implementation is very straight forward. The main thing I looked at was Nested transactions. The only issue is – possible overhead of using distributed transactions. For example:

void Foo1()

{

using {TransactionScope ts1=new TransactionScope();}

{

using (SqlConnection cn1=new SqlConnection)

{

cn1.Open();
//Do some functionality
foo2();

}

ts1.Complete();

}

}

void Foo2()

{

using {TransactionScope ts2=new TransactionScope();}

{

using (SqlConnection cn2=new SqlConnection)

{

cn2.Open();
//Do some functionality

}

ts2.Complete();

}

}

Does it create a distributed transaction with ts1 and ts2? How much overhead is there? Would it be more efficient if I re-use open transaction and open connection instead of just re-creating them? I will need to run some tests.

Also how does it work internally? In the sample code Connection is disposed off before TransactionScope is disposed. How is it possible to commit transaction after connection is closed. TransactionScope probably keeps track of all the opened connections and doesn't let them close till transaction is completed.

I still need to do some more testing to see if I need to switch or not.

4. How much of DbCommand, DataAdapter, etc… functionality to hide?

Let's take a look at executing a sql statement using SqlCommand

using (SqlConnection connection1 = new SqlConnection(connectString1))
{
connection1.Open();

// Create the SqlCommand object and execute the first command.
SqlCommand command1 = new SqlCommand(commandText1, connection1);
returnValue = command1.ExecuteNonQuery();
}

In my code under any DataObject I would use the following:

XConnection cn=new XConnection();

cn.GetCmd().ExecuteSql(commandText1);

XConnection automatically load ConnectionString from config file. It can be overriden through a property.

GetCmd() returns XCommand object which provides common Sql methods: ExecuteSql, QueryLookupInt, LoadListStr, etc…

ExecuteSql method will generate the command and automatically open and close connection.
This is still a big question for me. Many of these functions I have written before .NET 2, so I still need to see what is available.

Here is the final list of XLib Db classes.

XLib.db Classes

  • XConnection
  1. Provides generic access to Sql Server, Access, Oracle, etc…
  2. Handle transaction start/end/commit
  • XDataObject
  1. Exposes connection object
  2. Implements nested transaction scope. So I re-use a transaction if it already exists
  3. Implements nested connection opens scope. So I re-use open connection if it is already open.
  • XDataReader
  1. Automatically convert db values into INullable data types.
  2. Internally use .NET DataReader.
  3. Efficient paging (use PAGE_INDEX() in Sql Server
  • XDataWriter
  1. Automatically convert INullable data into db values. Handle DBNull.
  2. Internally use DataSet and DataRow
  3. Can insert, update, delete data in one table
  4. Generate INSERT, UPDATE, DELETE statements dynamically. Don't use SqlCommandBuilder, since it is a huge hit to performance.
  • XQuerybuilder
  1. Allow for ANSI or SQL-86 notation.
  2. Parse text representing SQL query into the object
  • XDataRecordReadOnly
  1. Abstract class with Load method
  2. Uses XDataReader to read data from one table
  • XDataRecord
  1. Derived from XDataRecordReadOnly
  2. Abstract class with Save, Delete methods
  3. Uses XDataWriter to write/delete data to one table

April 5, 2006

Foundation for the New Framework

Filed under: XLib Framework — Eric P @ 10:54 am

A project can only be as good as its foundation. If a house foundation is shaky, it doesn't matter how great the design is above ground. At every step, builders will have to deal with issues created by bad foundation.

Microsoft recently came with an excellent attempt at a foundation – .NET 2.0 and VS 2005. It tries to do everything, and succeeds in most cases. By writing a framework on top of .NET 2.0 I will try to fill the gaps in the specific area that I spend most of my development time: N-tier web applications.

My RAD framework is based on .NET 2.0 and Sql Server 2005. When I am finished I will make the framework open to the public, because I think that's the best way to improve it quickly.

The framework will consist of three major pieces:

XLib — base API for DataAccess, IO Access, Business Logic, etc…

XCodeGenerator — for generating classes and web pages from database tables

XWebSiteTemplate — generic modules for building the sites:

* User Manager

* Content Manager

* Email Manager

* …

Right now I am half of the way through the XLib, so there is plenty of work to do.

Create a free website or blog at WordPress.com.