Determining row counts for all tables in a database

Here is a usful snippet if you want a way to get the number of rows in each table in your database. I use this in an admin-only page of the web application to provide some at-a-glance statistics. It is also really useful in unit tests for checking the correctness of business logic that may create new entries in several tables in one transaction.

SQL snippet

The bit of SQL is quite straightforward, once you delve down into the depths of SQLServer’s system tables:

SELECT
   so.name AS TableName,
   MAX(si.ROWS) AS [RowCount]
FROM
   sys.sysobjects AS so
INNER JOIN
   sys.sysindexes AS si
   ON OBJECT_ID(so.name) = si.id
WHERE
   (so.xtype = 'U')
GROUP BY so.name
ORDER BY TableName

Presenting in a page

There are a number of ways of getting this into an ASP2 page. I chose to do this via a new table adaptor, and to wrap the query in an Administration class in the business logic layer.

Paste the SQL snippet from above into the query builder to create a new table adapter on the data designer – I have a separate “admin.xsd” to keep these non-user level types away from the core application data types. By default you will get an adapter called “sysobjectsTableAdapter” as it picks its name up from the first table in the query. You can change this if you need to.

You can now go direct to an ASP page by pointing an ObjectDataSource directly at this table adapter, or you can wrap it in an intermediate layer.

Unit test example

My unit test framework has a database reset mechanism that empties all tables and then creates a small set of known test data using the business logic layer (BLL). This empty and reset is done in the test fixture setup, and the subsequent raft of tests use a variety of methods to valid the integrity of the data.

A key test is ensuring that the expected number of rows in various tables have been created. This is particularly important as there are a number of linking and cross reference tables that are not directly seen by a user, but are there for the efficiency of the schema. So checking all these have been set correctly after the BLL has done its work is vital.

In the test class I have something like this :

[TestFixture] public class DBReset
{ ....
   private Dictionary TableRowCounts  = new Dictionary ;
   ...
    [TestFixtureSetup]
    public void FixtureSetup()
    {
        TableRowCounts.Add ("Addresses", 6);
        TableRowCounts.Add ("Agencies", 1);
        ...
    }
}

This sets up a list of all the tables I am interested in and maps the expected number of rows for each table after my fixture setup has initialised the database with known data.

I then have the following unit test as part of this fixture:

 [Test]
 public void CheckRowCountsExpected()
 {
    // Verifies that the correct number of rows in each database
    // has been created as a result of the reset and test
    // data initialisation.
    AdminBll abll = new AdminBll();
 
    Admin.sysobjectsDataTable tabs = abll.GetTableRowCounts();
    foreach (Admin.sysobjectsRow trow in tabs)
    {
       if (TableRowCounts.ContainsKey (trow.TableName))
       {
          //Only check the tables specified in the dictionary
          Assert.AreEqual(TableRowCounts[trow.TableName],
             trow.RowCount,
             "Wrong rowcount for table " + trow.TableName);
       }
    }
}

I also have a second test that verifies the admin query against each table one at a time using direct SELECT COUNT queries in SQL.

Leave a Reply