Friday, 12 June 2009

DataSet with Multiple Tables to EXCEL Sheets

In this project, I had to convert the DataSet with multi DataTables into Excel Report with Sheets.

First I thought adding DataSet into DataGrid(dg) using DataSource and then using dg.RenderControl(_htmlTextWriter) would work. However, DataGrid can render only one DataTable and thus that method was failed.

So, I tried to embed Microsoft.Office.Interop.Excel component and use its classes. However, I got stuck with permission errors. If a user does not have OFFICE and if he/she does not know how to change the permission setting, this will bring hell lot of distraction to the user.

Then again, I had to change the method. I surfed the google and there is this Excel.xsl (ref. 1) to use to transform the DataSet XML to Excel XML.

ref. 1
/***********************************************************************************/

xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:user="urn:my-scripts"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" >

































/***********************************************************************************/

So I used the code (ref. 2) to check what the XMLDocument's schema is like. It starts with NewDataSet and then with DataTable's Name for each DataTable.

ref. 2
/***********************************************************************************/
string filename = Server.MapPath("XmlDoc.xml");

//Create the FileStream to write with.
System.IO.FileStream stream = new System.IO.FileStream
(filename, System.IO.FileMode.Create);

//Create an XmlTextWriter with the fileStream.
System.Xml.XmlTextWriter xmlWriter =
new System.Xml.XmlTextWriter(stream,
System.Text.Encoding.Unicode);

XmlDataDocument xmlDataDoc = new XmlDataDocument(excelBook);
xmlDataDoc.Save(xmlWriter);
//excelBook.WriteXml(xmlWriter);
xmlWriter.Close();

/***********************************************************************************/

So, using the code (ref. 3) transform the DataSet XML (ref. 2) using XSL (ref. 1)

ref. 3
/***********************************************************************************/

XmlDataDocument doc = new XmlDataDocument(_DataSet);
StringWriter sww = new StringWriter();
XslCompiledTransform xtt = new XslCompiledTransform();
xtt.Load(Server.MapPath("Excel.xsl"));
xtt.Transform(doc, null, sww);

/***********************************************************************************/

Now, we had the Excel XML schema. Yet, the Excel.xsl is adding all the DataTables in . Thus when the excel file was created, only one SHEET was there. I want the excel files to have one SHEET for one DataTable.

Thus, I thought adding "for-each" under the template would create for each DataTable. It was impossible to use it since the DataTables are stacked in DataSet with TableNames {e.g. if the table names are not given, it takes Table1, Table2, Table3, etc., as default names} rather than "Table" tags.

Later, with the help of my colleague, I found out that adding each DataTable's XML data into STRING object and remove the duplicated XML tags such as "". As the DataTables are looped through, the "Workbook" tag is added seperately(ref. 4)

ref.4
/***********************************************************************************/

System.Text.StringBuilder swAll = new System.Text.StringBuilder();

swAll.Append(@"
xmlns:o=""urn:schemas-microsoft-com:office:office"" xmlns:x=""urn:schemas-microsoft-com:office:excel"" xmlns:ss=""urn:schemas-microsoft-com:office:spreadsheet"" xmlns:html=""http://www.w3.org/TR/REC-html40"" xmlns:msxsl=""urn:schemas-microsoft-com:xslt"" xmlns:user=""urn:my-scripts"">");

/***********************************************************************************/

After all, the multisheets creation works fine. Now, I need to consider about the STYLES. I take wiki_excel_styles as an example. So I added the into the XML String Object as (ref. 5)

ref. 5
/***********************************************************************************/

/* Append Styles */
swAll.Append(@"


");
/***********************************************************************************/


In that case, each node in the XML should be looped through to add the attributes: StyleID.

XmlNode root = xmlDoc.DocumentElement;
XmlNodeList node = root.SelectNodes("/Workbook/Worksheet/Table");

The above code does not work as the EXCEL Schema has namespaces in it. After fiddling for some times, again with the help of my colleague, I gained the knowledge of useful XmlNamespaceManager. Changing the code (ref. 6) by adding Namespace could enable the XmlDocument to select the XPath node.

ref.6
/***********************************************************************************/

XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("ss", "urn:schemas-microsoft-com:office:spreadsheet");

XmlNode root = xmlDoc.DocumentElement;
XmlNodeList node = root.SelectNodes("/ss:Workbook/ss:Worksheet/ss:Table", nsmgr);

xxxxxxxxxxxxxxxxxxxxxxx

XmlAttribute _attr = xmlDoc.CreateAttribute("ss", "StyleID", "urn:schemas-microsoft-com:office:spreadsheet");
_attr.Value = "s12";
cells.Attributes.Append(_attr);

/***********************************************************************************/

Everything's working fine and now need to adjust the column. AutoFitWidth does not work for TEXT; works only for NUMBERs. So I need to add something like "" right after the "TABLE" tag before calling all the "ROW" tags.
Adding the following code (ref. 7) let the very first column expand with the specified width.

ref. 7
/***********************************************************************************/

XmlNode _column = xmlDoc.CreateNode(XmlNodeType.Element, "ss", "Column", "urn:schemas-microsoft-com:office:spreadsheet");
XmlAttribute _colattr = xmlDoc.CreateAttribute("ss", "Width", "urn:schemas-microsoft-com:office:spreadsheet");
_colattr.Value = "300";
_column.Attributes.Append(_colattr);

/***********************************************************************************/

you can also check on this website for sample project too.

There may be a problem with file extension such as xls and xlsx. This site tells about Excel 2007 XML format.

Great! Well done! now i can enjoy my weekend :P

Thursday, 6 November 2008

Report in PDF format

At work, I had to convert a list of bitmap images to PDF report in web service.

So let's see how to use Microsoft.Reporting.WebForms.

After referencing to Microsoft.Reporting.WebForms from your web form, you will be able to use ReportViewer control. As my project needs to render the report dynamically, I chose LocalReport object to create a report instance.

My colleague, Lukasz, has worked on crystal-report-alike projects and he helped me alot in creating the dynamic report.

What needs to be displayed on the page are label showing "part 1" or "part2" and Jpeg image.
In order to design for the dedicated report, I created report file, Report.rdlc. Then on the report designer view, you will see the report page and Website Data Sources view as well as Toolbox.

I need a resource object for report called as ReportDataSource. In that source, what I need is to have label and image. So, dataset is created by clicking Add New DataSource in Website Data Sources view. You can rename your DataSet by right clicking on the name in code behind and choose "Refactoring name" and also renaming in the Properties window.

I dragged and dropped the DataTable control named tblReport from the Toolbox onto DataSet.xsd. Then right click on the DataTable and chose "Add" and then "Column". I created 2 columns as dcLabel and dcImage. Changed the DataType of the dcImage to System.Byte[].

Then I went back to Report.rdlc and drag-and-dropped the Table onto the report page. The table will have 2 Rows (for label and image) and 1 Column. I dragged dcLabel from DataSet >> tblReport object into Row[0] Column[0] and dcImage into Row[1] Column[0]: they appeared as "=Fields!dcLabel.Value" and "=Fields!dcImage.Value". In image's properties window, set MIMEType as image/jpeg and Source as Database. Image's sizing property was set as FitProportional.

Report's layout can be adjusted by going to VS2008's Report menu, and, Table's layout can be adjusted by selecting the whole table and rightclicking to choose properties. Normal A4 page size is 21cm and 29.7cm. So you can adjust the page layout not more than the standard size and the contents within the boundaries.

Then in the [WebMethod] of the web service, report is dynamically created using LocalReport.

DataTable to add into the datasources of the LocalReport can be created by declaring an object as the name you give to the DataSet.axd. Then by using .Newxxx(), you can create a new data row and can add specific data into the columns of that row.

e.g.

LocalReport report = new LocalReport();
report.ReportEmbeddedResource = "{WebService project name}.{Report name}.rdlc;
report.DataSources.Add(new ReportDataSource({DataSet name}, {DataSet's DataTable}));
report.EnableExternalImages = true;
report.Refresh();

In report form's [Table]'s prperties, {General >> Dataset name:} should be the same as code behind's datasource's [ReportDataSource]'s name.

Rendering to PDF could be done as in the following example:
string mimeType;
string encoding;
string fileNameExtension;
string[] streams;
Microsoft.Reporting.WebForms.Warning[] warnings;
byte[] pdfContent = report.Render("PDF", null, out mimeType, out encoding, out fileNameExtension, out streams, out warnings);

Page number can be added in the footer section by creating a text box and adding the following line in the text box:
=Globals.PageNumber & " of " & Globals.TotalPages

After you have converted your byte array to file using filestream, you can then check your file to see if it renders as it's supposed to be.

You can optimise the size and quality of the image file: http://www.glennjones.net/Post/799/Highqualitydynamicallyresizedimageswithnet.htm

Tuesday, 12 August 2008

SQL Server 2005 High-Availability Strategies

Two separate instances (Default + Named) / servers

Log Shipping

A very simple way of keeping a full copy of a database on another system.

#Transaction log:
  • It records all data modifications;

  • insert + update + delete statement >> transaction log >> the log is checkpointed >> the data is written to the database;

  • helpful in maintaining the integrity of the db.

  • [primary server] --T-log file--- [secondary/standby server]

Benefits:

  • Fault tolerance

  • Offloading backups

  • Offloading query processing

  • Doesn't require extra hardware + provide a full warm spare

Log shipping

does not provide automatic failover.

can keep the primary server fully online at all times. Lengthy, time-consuming backups can be done on the separate server.

standby server -> read-only for query processing; all users need to be disconnected during the data restoration.

Requirements:

databases -> ***full / bulk-logged*** recovery model; cannot be simple recovery model;

SQL server Standard
/
SQL server Workgroup
/
SQL server Enterprise
on all server instances involved in log shipping.

servers involved -> same case sensitivity settings

for Configuration
must be a sysadmin on both servers
steps: (1) backup the primary + restore on the secondary (2) enable log shipping

Monitor Server
a third server;
records the history + status of log backup and log restore operation;
can raise alerts if any of the opations fail;

terms for secondary servers and spares:
cool = can be powered up & restored
warm = standby; automated method to keep up to date;
*hot = a cluster; keep up to date + automatic failover to the secondary server

TIP To decrease the latency between the primary and standby servers, simply change the timing in the schedules of the jobs. On the primary server, change the schedule of the backup job. On the standby server, change the schedules of the copy and restore jobs.

Procedures for changing Roles
  1. Manually failover from the 1' db to 2' db


  2. Disable log shipping jobs


  3. Reconfigure log shipping (if desired) to swap the roles


  4. Bring the 2' db online (RESTORE cmd; NORECOVERY for each restore except the last)

Database Snapshots

are only available in the Enterprise edition

created at a moment in time

used for reporting purposes for that given time

concept referred to as copy-on-write;

Purpose and Benefits:

  • Protecting data from user error


  • Safeguarding data against admin error


  • Maintaining historical data for report generation


  • Using a mirror db that you are maintaining for availability purposes

EXAM TIP One of the great benefits of database snapshots is the ability to overcome user errors. By creating database snapshots on a regular basis, you can mitigate the impact of user errors such as inadvertently deleting data, or of an administrative error such as what might occur during a manual bulk-load process.

Creating and Using a Database Snapshot

snapshot creation permission ~ db creation permission

E.G.
CREATE DATABASE AdventureWorks_Snapshot_0900 {name + time} ON
( NAME = AdventureWorks_Data, FILENAME =
'C:\Program Files\Microsoft SQL
Server\MSSQL.1\MSSQL\Data\AdventureWorks_Snapshot_0900.ss' )
AS SNAPSHOT OF AdventureWorks;

RESTORE DATABASE name_of_database_to_be_restored FROM DATABASE_SNAPSHOT = 'name_of_the_snapshot';

Database Mirroring

Significant difference bw. log shipping & db mirroring:

datbase mirroring -> automatic failover

Principal SQL server ---State data exchanged // T-Log file --- Mirror SQL server

Requirements:

  • sql server 2005 service pack 1


  • recovery model <= FULL


  • only datbases {except master + msdb + tempdb}; not servers


  • supported on SQL Server Standard + Enterprise editions

Benefits:

  • no additional hardware


  • as witness server => high availability


  • using with snapshots, db mirrors can be queried directly by users

Witness Server

to enable automatic failover / high-availability mode;

the db mirroring session must be in synchronous operating mode:
trasaction safety on (synchronous) {high availability}
transaction safety off (asynchronous) {high performance}

Database Mirroring Endpoints

endpoint = sql server object = to facilitate communication within db mirroring connections

a unique listener port

1 server instance <--> 1 db mirr. endpoint <-=> multiple db mirr.

E.G
CREATE ENDPOINT DB_Mirroring_Endpoint STATE = STARTED AS TCP ( LISTENER_PORT = 5088 ) FOR DATABASE_MIRRORING (ROLE=PARTNER);


its default state is stopped

select * from database_mirroring_endpoints

Implementation:

RESTORE DATABASE Chapter10
FROM DISK = 'C:\Chapter10_Full.bak'
WITH NORECOVERY,
MOVE 'Chapter10' TO 'C:\LogSecondary\ShipChapter10.mdf',
MOVE 'Chapter10_Log' TO 'C:\LogSecondary\ShipChapter10.ldf'
RESTORE LOG Chapter10
FROM DISK = 'C:\Chapter10_Log.bak'
WITH NORECOVERY

TIP The WITH NORECOVERY clause is critical. The mirrored database is not restored into a fully functional database, but is instead restored to a state that allows transaction logs to be constantly applied to it.

Replication

It distributes --publication-- parts of tables / views => articles

Publisher Metaphor
publishers + distributors + subscribers +
articles + publications + subscriptions (pull & push)

EXAM TIP When choosing articles for publication, you should also consider the objects you’ve created to optimize them. For example, if indexes were created to optimize the performance of queries against specific tables, you should consider including these indexes in the publication. If they are omitted, the queries could perform poorly on the Subscribers.

Methods:

Merge => tracks changes through triggers & metadata tables; multiple subscribers can update the same data; subscribers need to be able to change data offline & later synchronize changes with publisher; if subscribers require different partition of data; conflict detection & resolution; no access to intermediate data states; allows multiple subscribers to update data;
+
Transactional => changes through transaction log; starts with snapshot; occurs in near real time; access to intermediate data states; high vol. of transactional activity; when the publisher (or) subscriber is not a MSSQL server db;
+
Snapshot => when data rarely changes; out of date data on subscribers are acceptable; only small amounts of data are replicated; large vol. of data changes in a short period;

EXAM TIP The warnings for either long or slow merges over different types of connections can be very helpful in determining if merge replication is experiencing problems due to the network infrastructure. It could be that the merge replication is configured as best as possible, but connectivity problems are preventing merge replication to complete in a timely manner. Creating a warning with an alert allows you to be notified as soon as the problem is encountered.

Tracer tokens are used to easiliy measure latency esp.lly for subscribers.

Clustering

  • the ultimate high-availability solution


  • automatic failover of teh entire server


  • nodes = servers within a cluster


  • up to 8 nodes allowed;


  • most current cluster config. require that at least one node be inactive; N+1 nodes where N is the no. of primary servers


  • costy


  • difficult to configure & maintain


  • useful when we have one or two large databases

Number of Cluster Nodes Supported in Different Editions:

SQL Server Standard Edition => 2
SQL Server Enterprise Edition => 8
Windows Server 2003 Enterprise => 8
Windows Server 2003 DataCenter => 8



Thursday, 31 July 2008

SQL Server 2005 INDEXING

I like the quote said by "William James" (from MCITP Server 2005 Database Administration book):

~The art of being wise is the art of knowing what to overlook~

Anyway... here are the gists for INDEXES.

Indexes: Clustered + Nonclustered; Heap = the absence of index on a column

Clustered

Like a dictionary or phone book, the data is kept in *sorted* order

Leaf level rows = Data rows

Nonleaf level pages and data are in seperate storage areas

Only one clustered index on a table

PRIMARY KEY = Clustered by default

Nonclustered

Like the index in the back of the book.

Storage: 8 pages within an extent; 8KB for each page; so total 64KB for an extent;

When SQL Server reads data off the disk, it reads full extents at a time.

We can have up to 249 nonclustered indexes on a table.


Columns that are good candidates for indexes are _____

Primary keys and foreign keys

Cols that are frequently referenced in queries

Cols that are searched for ranges of key values (with WHERE clauses)

Cols that need to be sorted (used in the ORDER BY clause)

Cols that are frequently grouped together during aggregation (i.e., AVG func)


Columns that should not be indexed are _____

Cols that are seldom referenced in queries

Cols that aren't selective, or have few unique values

LOB (Large Object) data types {text + ntext + varchar(max) + nvarchar(max) + varbinary(max) + xml + image}

Composite Index

> 1 column

covering a query

When creating a composite index, one column is referred to as the key column, and the other columns are referred to as the included columns

Index *attributes* can also be learned at http://www.windowsitlibrary.com/Content/77/17/1.html

Fill Factor

fill factor 0 / 100 = 100 percent full
EXAM TIP The fill factor becomes a significant factor in the ultimate size of the index. Consider an index that’s 20MB with a fill factor of 100 percent.
How big would the index be if we set the fill factor at 50 percent, or allowed the pages to be half full? It would be twice as large.


Fragmentation

If you want to prevent fragmentation => use a fill factor appropriately for the number of inserts you expect so that you can prevent, or at least minimize page splits

Pad Index

It directs the system to use the same % as the fill factor when filling the nonleaf levels of the index.

Calculating Size

(S x R) / F

S = Size of index row
R = Number of rows in index
F = Fill factor

TempDB

If you have to frequently rebuild indexes and you leave the default of sorting the results in tempdb, you want to have the initial size of the tempdb set to a little bit larger than the largest index.

If tempdb doesn't start at the size that it needs to be, then Autogrowth will cause it to grow to the size needed. If it starts at 8MB and need to grow to 1GB insize, it'll have to resize itself 51 times!

While this will work, it is much more resource-intensive to have the database constantly resize itself than to set it to the size it needs to be originally. (from MCITP)

Creating an Indexed View

Three basic rules:

  • must be created with SCHEMABINDING option
  • objects must be referenced with a two-part name (i.e. schema.table).
  • the view must be deterministic (it cannot contain any non-deterministic funcs)

Statistics in SQL Server

Density

The % of duplicate rows in an index

Selectivity

The % of rows accessed or returned by a query

Viewing and Updating Statistics

Enable settings by default:

  • AUTO CREATE STATISTICS

  • AUTO UPDATE STATISTICS

DBCC SHOW_STATISTICS (tableName, indexName)

EXAM TIP A common symptom indicating statistics may be out of date is when queries begin to run slower than normal.

EXAM TIP A sudden jump in the number of stored procedures that are being recompiled could indicate that statistics have been updated.

Full-Text Index

Created on textual data to increase performance and capabilities with searches.

Steps:

Verify the database is enabled for full-text searches;

Create a full-text catalog;

Create a full-text indexes;

DataTypes = char + varchar + nvarchar + varchar(max) + varbinary(max) + XML + image

Clustered or nonclustered indexes are not useful with full-text searches

E.G.
SELECT DATABASEPROPERTYEX('AdventureWorks', 'IsFullTextEnabled')

EXEC [AdventureWorks].[dbo].[sp_fulltext_database] @action = 'enable'

CREATE FULLTEXT CATALOG ftCatalog as DEFAULT

CREATE FULLTEXT INDEX ON HumanResources.JobCandidate(Resume) KEY INDEX
PK_JobCandidate_JobCandidateID;

SELECT *
FROM HumanResources.JobCandidate
WHERE CONTAINS(Resume, ' "mechanical engineering" ');

Database Engine Tuniting Advisor (DTA)
● Recommend indexes (clustered and nonclustered) to create
● Recommend indexes to drop
● Recommend indexed views
● Analyze the effects of the proposed changes
● Provide reports summarizing the changes and the effects of the changes

Tuning Options
Physical Design Structures (PDS) in use database => what indexes / indexed views

Partitioning: Full + Aligned

PDA to keep in database => existing indexes / indexed views to be kept

Index Maintenance
Enable to drop unused indexes to eliminate the needless overhead.

DMV (Dynamic Management Views + Functions) :

  • Server-scoped -> VIEW SERVER STATE

  • Database-scoped -> VIEW DATABASE STATE
Fragmentation
logical (pages are out of order)
+
extent (extents are out of order)

TIP The DBCC SHOWCONFIG command has been deprecated in SQL Server 2005 and replaced with the sys.dm_db_index_physical_stats dynamic management function.

Degragmenting a Fragmented Index
Reorganising = ALTER INDEX REORGANIZE {online; statistics are not updated during this operation}

Rebuilding = ALTER INDEX REBUILD {online / offline; defaults -> offline}

Recreating = The index can be dropped and re-created from scratch. {offline;}

In SQL Server 2005, it is common to use the tempdb when rebuilding indexes. Because of this the initial size of the tempdb database is an important consideration. Set it to be a little larger than the largest index.

To easily determine how useful an index is, you can use the sys.dm_db_index_usage_stats dynamic management view.

DBCC (Database Console Commands)
DBCC CHECKDB = to check database integrity;
DBCC OPENTRAN = to check for open transactions within a database;
DBCC SQLPERF = to get information on the transaction log;

Deprecated command Alternative recommendation
INDEXDEFRAG => ALTER INDEX
DBREINDEX => ALTER INDEX
DBREPAIR => DROP DATABASE
SHOWCONTIG => sys.dm_db_index_physical_stats.
EXAM TIP Expect to see some of these deprecated commands as incorrect answers on the test. If Microsoft has deprecated the commands, now saying we should not use them, don’t expect them to be a correct answer on the test.

Filegroups

Single filegroup <- the .mdf file (named databaseName_data by default)

First filegroup - Primary <= primary filegroup

*The transaction log is a seperate file & is not kept in a filegroup at all*

Additional filegroups can be created for the following reasons:

Performance + Recoverability + Partitioning

possibilities:

  • One file and One filegroup
  • Multiple files and One filegroup
  • Multiple files and Multiple filegroups

extension of the secondary file is .ndf

ALTER DATABASE Chapter7 ADD FILEGROUP Secondary;
ALTER DATABASE Chapter7
ADD FILE (NAME = 'SecondFile', FILENAME = 'C:\Program Files\Microsoft
SQL Server\MSSQL.1\MSSQL\DATA\ SecondFile.ndf',
SIZE = 1024KB, FILEGROWTH = 1024KB)
TO FILEGROUP Secondary

Here is a good article about the difference between VARCHAR and NVARCHAR:

http://searchsqlserver.techtarget.com/tip/0,289483,sid87_gci1266201,00.html

Tuesday, 1 July 2008

Restart my routine

Oh, how dusty this blog is. It's been nearly a year!

Like rebooting the hard-drive, I now realise that I have to refresh myself and replan for the future career path. Otherwise, I will get stuck at the same place for several years with no improvement.
I hope this is the real longlasting motivation for me.

From today, I am giving myself 90 days of learning to acheive 70-431 cert.
I will try my best to update this blog with all the things I've learnt so far.

Thursday, 5 July 2007

Master FindControl

A web project I am developing has nested Master Pages.

Within Main Master Page has two ContentPlaceHolder with IDs ContentPlaceHolder1 and ContentPlaceHolder2 respectively.

Within ContentPlaceHolder1 resides another Master Page which I will name it as Second Master Page for an easy usage. The Second Master Page has one ContentPlaceHolder with ID called ContentPlaceHolder2.

Under the Second Master Page's ContentPlaceHolder2 is the page I'm working on which I will name it as XX.aspx.

XX.aspx contains custom composite controlsthat are checkboxes and dropdownlists.

What I would like to do is: after clicking on SAVE button, the data related to the checked checkboxes and its related dropdownlist options will be stored in the database.

The VIEWSTATE of the custom controls are kept on POSTBACK and all I need to do is to look for those custom controls on XX page and get the data.

I first tried to get content place holder control on XX page by using the following code:

ContentPlaceHolder _content = (ContentPlaceHolder)Master.FindControl("ContentPlaceHolder2");

However, that code returns NULL.

After figuring out what it does for some times, I changed the code as:

ContentPlaceHolder _pcontent = (ContentPlaceHolder)Master.Master.FindControl("ContentPlaceHolder1");
ContentPlaceHolder _content = (ContentPlaceHolder)_pcontent.FindControl("ContentPlaceHolder2");


if (_content != null)
{
x x x
}


Now I understand that in order to avoid the ambiguous ContentPlaceHolder ID names in nested Master Page, I shall start searching from the top parent Master Page.

Now I'm satisfied that I can retrieve data from the controls on my XX page :)