Wednesday 28 March 2007

GridView : Getting updated cell values

When using a gridview the RowUpdating event arguments has a property (e.)NewValues.
There is a problem if the GridView datasource is not set to s DataSourceObject, these NewValues remain blank.
To populate use the following code:
GridView gv = (GridView)sender;
for (int i = 0; i < gridView.Columns.Count; i++)
{
DataControlFieldCell cell = gv.Rows[e.RowIndex].Cells[i] as DataControlFieldCell;
gv.Columns[i].ExtractValuesFromCell(e.NewValues, cell, DataControlRowState.Edit, true);
}

Monday 26 March 2007

Nhibernate: Date time field null on insert

Receiving exception when trying to save a record the stack tarce identified theproblem as a null value for a DateTime field.
This is caused by either:
  1. Property not marked as nullable (? after Type in property declaration)
  2. Existing record being flushed that contains an invalid null value for datetime.

NHibernate: Object not set to instance on save

When saving I received 'Object not set to instance', from the stack trace the object in question was identified as the VerisionNo.
This was correctly defined for the table in question, after investigation it was identifeid as being a link table that was being flushed which had an existing record with a Null value for the VersionNo.
This record had been either manually entered or entered prior to the versionNo field being defined as NotNull.

Friday 23 March 2007

RowDataBound checking if row is in edit mode

The RowState property of a grid row can hold more than one value using bitwise logic.
If you want to test if a row is in edit mode then use:

if ((e.Row.RowState & DataControlRowState.Edit) > 0)

The RowState will also have a value of DataControlRowState.Alternate for every other row.

Thursday 22 March 2007

GridView : DIsplaying results of function using DataItem as parameter

Instead of just displaying the actual value of a field in a column (<%# Bind("Hours") %>) you can also call a function that uses the value to get another value.
e.g.
If we have ClientID but we want to display ClientName (another tabel in the db) we can assign:
Text='<%# GetClientName(DataBinder.Eval(Container.DataItem, "ClientID")) %>'

We then have a function in the page code:

protected string GetClientName(object iD)
{
return GetClientNameById(iD);
}

Note. the parameter must be defined as object because the actual type is unknown until binding.

Spring: Error instantiating context spring.root

Had the exception "Error instantiating context spring.root" when attempting to create an object.
This was caused by not including the assembly reference that the object belonged to in the web site.

Tuesday 13 March 2007

Updatepanel : Making other panels visble/invisible

Had a problem making multiple panels visible / invisible inside an UpdatePanel. The problem was occurring when I wanted to display different panels based on wether a user was logged in or not.
As an example I created the following user control with two panels which should alternatively be displayed.
When the Top button is clicked the code was storing in a session object that the user is logged in.When the Top button is clicked the code was storing in a session object that the user is logged out. During the Render method of the contorl if the seesion object was set to Logged In then the bottom panel was set visible=true and the top panel set to visible=false (and vice versa when logged out)
This worked, until another UpdatePanel on the page performed a partial postback, then both panels were being displayed.

Assumption of what was happening: The problem seems to be that the setting of the visible=true|false was being made in the wrong place. Setting the values in the Render method mean that they are not then stored on the control state; when a different updatepanel performs a partial postback it appears the control state is used to identify what elements of the page need updating. In the above case both panels has visible=true set in the control state.
Fix: To fix the problem the setting of the panel visibilty was moved to the PreRender method (after PreRender, SaveState is called, the Render).

Validators not working in UpdatePanel after partial postback

There is a problem with Validator controls not being displayed in (Ajax) UpdatePanel after another updatepanel performs a partial postback.

i.e. Validators work fine when page is first loaded; then another UpdatePanel control performs a partial postback; the original validator is no longer displayed.

This is dues to a problem with release v1 of Asp Ajax. A patch is to be released to fix this, alternatively compatible controls can be downloaded

See this link for more details

Monday 12 March 2007

Validators & Multi-view

Validators don't (seem to) work in MultiView view.

May be due to Ajax v1 & validators see above.

Thursday 8 March 2007

NHibernate Flush before Query

Was having a problem with following:
  1. Start Session
  2. Read object/record (presentation layer)
  3. Update record/object im memory (presentation layer)
  4. Run query to check changes valid (biz layer).
  5. If 4 ok commit changes inside transaction (biz layer)
  6. End session
Step 4 was identifying a problem and so steps 5 was not completed (i.e. no explicit Commit was called), the problem was that the record changes were still being written to the database.

This is caused by the FlushMode of the session be set to Auto. When set to auto NHibernate will sometimes flush the persistent obejct prior to performing a query.

There are a few solutions to this:
  • Perform updates to object after query (not applicable in this case due to layers)
  • Disconnect object prior to updating (Evict)
  • Change FlushMode to Commit
The solution decided upon was to change FlushMode to Commit and to also clear the session if a transaction fails and rollback is called.

Tuesday 6 March 2007

Error on DataBind() of DropDownList:, invalid SelectedValue

Getting error:

has a SelectedValue which is invalid because it does not exist in the list of item


The SelectedValue before the databind is set to "" (i.e. blank string)
The error occurs because the data being bound does not include a value of "" (blank string).

To fix it:
  1. Set AppendDataBoundItems=true for control
  2. Clear the list prior to databind; .Items.Clear();
  3. Add a blank item: .Items.Add(new ListItem("", ""));
  4. Call .DataBind();

Monday 5 March 2007

How to map to a Generic IDictionary

Say you have a standard nHibernate Bag that maps to a IList

C# Definition

public virtual IList<UserGroup> Groups;


nHibernate Mapping

<bag name="UserGroups" table="UserGroup">
<key column="UserID"/>
<one-to-many class="UserGroup"/>
</bag>


You can change this to a IDictionary by changing the IList to a IDictionary in the Business Entity, then change the bag to a map,and adding a index setting to the nHibernate mapping.

So the above would be changed to

C# Definition

public virtual IDictionary<int,UserGroup> Groups;


nHibernate Mapping

<map name="UserGroups" table="UserGroup">
<key column="UserID"/>
<index column="GroupID" type="int"/>
<one-to-many class="UserGroup"/>
</map>


Where of course the index column is the column that you will search on, and the type is the type of the column.

NOTE - The Key Column and the Index column cannot be the same, but then thinking about that it would be pointless because the key value would be the same on all the keys of the dictionary.

NHibernate error loading class

Got the error:

Could not load type '...Page, SalecoreContent', check that type and assembly names are correct


Was caused by an incorrect class="Page" reference in one of the object mapping files.

Friday 2 March 2007

nHibernate Get or Load?

Session.Get and Session.Load do very similar things, the difference is.

.Get will return null if a record is not found.
.Save will return an exception if a record is not found, and if it can use a proxy, it will return a proxy, so you won't get the exception until you try to actually use the object.

If you are not sure that a record exists then use .Get and check that the object isn't null.

NHibernate:How do I know a field is dirty?

The problem arose that I needed to know if a field had changed just prior to saving:

  1. Presentation layer reads object/record
  2. Presentation layer changes object field value
  3. Presentation layer calls business layer to update the object/record
  4. Business layer needs to know if a certain field has changed to perform extra processing
When the record is read (in step 4) from the database it actually comes from the (session) cache and therefore holds the values of the changed (but not yet persisted) fields.

The solution seems to be either clear the cache or tell the business object that the field has changed. The clear-the-cache solution was not tried, would have been along the lines of Session.Evict(object).