Devlico.Us
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @devlicious

Billy McCafferty

October 2006 - Posts

  • Common SQL Scripts and Tips

    Since embracing NHibernate, I've reveled in not writing any ADO code.  On the other hand, I've become a bit rusty, and a bit nostalgic for that matter, with SQL these days.  To my chagrin, I find myself having to look up bits and pieces of SQL that I used to be able to recite in my sleep.  To help cut down on the number of times SQL docs needs to be opened, below is a quick summary of the most common and useful SQL scripts for SQL Server 2005 maintenance; most apply to 2000 as well.  (For the record, I'm no DBA but just a lowly developer who uses SQL daily.)

    Return "quick" row count

    If you're dealing with larger tables, SELECT COUNT(*) can be a time consuming operation.  For a very quick row count - albeit, not guaranteed to be accurate in real time - use the following instead:

    SELECT rows
    FROM sysindexes
    WHERE id = OBJECT_ID('table_name')
    AND indid < 2

    Delete all table rows

    Similar to using SELECT COUNT(*), the most common approach isn't always the most efficient.  Using DELETE FROM table_name is time consuming - and storage consuming - as deletions create log entries.  For an incredibly fast deletion of all table records, but - as a warning - without the log entries possibly needed for a recovery:

    TRUNCATE TABLE table_name 

    Truncate the DB log

    If you find yourself running out of storage space on your hard drive, it may be due to an enormous SQL log file.  The following allows you to truncate and shrink the log file to a smaller size...2 MB to be exact.  Warning:  dumping the transaction log has ramifications with respect to recovery options (or lack there of), so use at your own risk!

    DUMP TRAN db_name WITH NO_LOG
    DBCC SHRINKFILE (db_log_name, 2) WITH NO_INFOMSGS

    Shrink the DB

    The following will remove empty space from your DB file, leaving 10% left open.

    DBCC SHRINKDATABASE (db_name, 10)

    Limit Logging Altogether

    Although you can't turn off logging altogether in SQL Server, you can limit logging by setting the DB's recovery mode to "simple."  For recovery purposes, it's recommended to keep it on "full" recovery mode for the rest of the time.

    -- Limit logging with "simple" recovery mode
    ALTER DATABASE db_name
    SET RECOVERY SIMPLE

    -- Restore logging to "full" recovery mode
    ALTER DATABASE db_name
    SET RECOVERY FULL

    ...There are many variations and options to each of the following, as described in your SQL docs...

    Add a column to a table

    ALTER TABLE table_name
    ADD column_name type(length) NOT NULL
    DEFAULT default_value

    Drop a column from a table

    ALTER TABLE table_name
    DROP COLUMN column_name

    Modify an existing column

    ALTER TABLE table_name
    ALTER COLUMN column_name type(length) NOT NULL

    Add a foreign key

    ALTER TABLE foreign_key_table_name
    ADD FOREIGN KEY (fk_name)
    REFERENCES primary_key_table_name(pk_name)

    What's listed here are my most commonly used, and regularly looked up, SQL scripts and optimization tricks.  Hopefully it'll save you some lookup time as well...feel free to submit other snippets that you feel should be added to the list of bare essentials.

    Billy

  • Show User-Friendly enum Translations

    It's common to populate a drop-down box with enum values or, similarly, to display an enum setting to the user.  The problem is that enum values usually aren't very pretty to look at.  (Memories of hoping QA wouldn't spot "OrderShipped" come to mind.)  In a previous post by Joe Niland, Joe suggested that attributes be used to maintain the user-friendly version of enum values.  What follows is a solution for doing just that.

    What we need is a class that will satisfy the following unit-test:

    When a description is provided for an enum value, via the "Description" attribute, then the provided description is returned.  When a description isn't available, the ToString version of the enum value, with spaces put before each capital letter, is returned, instead. 

    So then to satisfy the unit test:

    This should make a useful addition to any utility library.

    Billy

  • Examine XML of Web Service Response

    While working on winning Netflix' million, I came across a need to examine the raw XML returned by a third party web service.  After a couple desk-pounding hours, I finally found a simple solution which works equally well in both Web and Windows apps.

    1. Install Web Services Enhancements (WSE) 3.0
    2. Add a project reference to Microsoft.Web.Services3
    3. Modify the web service proxy to inherit from Microsoft.Web.Services3.WebServicesClientProtocol instead of System.Web.Services.Protocols.SoapHttpClientProtocol.  (This augments the proxy's capabilities.)
    4. The response's raw XML may then be retrieved immediately after the call to Invoke as ResponseSoapContext.Envelope.InnerXml

    Optionally, log4net may be employed so as not to interrupt the application while it goes about its business...

    1. Add a project reference to log4net
    2. Add log4net configuration to app.config or web.config.  For example:

      <!-- If you want to turn log4net off completely,
      include threshold="OFF" below
      -->

      <log4net threshold="ON">

          <appender name="LogAllToFile"
              type="log4net.Appender.FileAppender">

              <file value="MyLog.log"/>

              <appendToFile value="false"/>

              <layout type="log4net.Layout.PatternLayout">

                  <conversionPattern
                      value="%d [%t] %-5l - %m%n%n"/>

              </layout>

          </appender>

          <root>

              <!-- ALL, DEBUG, INFO, WARN,
              ERROR, FATAL, OFF
      -->

              <priority value="ALL"/>

              <appender-ref ref="LogAllToFile"/>

          </root>

      </log4net>

    3. Initialize log4net when the application starts with a call to XmlConfigurator.Configure();
    4. Add the following code immediately after the call to Invoke in the proxy web service:

      log4net.ILog logger = log4net.LogManager.GetLogger(typeof(MyProxyClassName));

      logger.Info(ResponseSoapContext.Envelope.InnerXml);

    With log4net turned on, the raw XML within the web service response will get written out to the log file and the application will not be interrupted.

    Billy

  • (My) Default ASP.NET Architecture

    In developing any software application, it's important to keep things as simple as possible and add complexity only when needed.  (I spoke about this in a previous post, Planning for vs. Reacting to Change.)  On the flip-side, a certain amount of architecture may be assumed at the start of a project depending on the type of application being developed.  Selecting an appropriate, default architecture provides your application with a solid foundation and offers guidance for other developers, and yourself, for further development.  This entry describes a suggested, default architecture for data-driven, ASP.NET applications for both individual and team development.  Disclaimer:  it is important to note that there are many appropriate architectural foundations and this is just one of them.

    Architectural Assumptions

    In providing an architectural approach, some assumptions are made concerning the project goals.  These assumptions should be used as a litmus test to determine if the described architecture may be an appropriate fit for your ASP.NET application.

    • Testability is of utmost importance.  If test-driven development (TDD) will not be practiced, then most of what follows becomes a moot point.
    • Separation of concerns is strongly enforced.  This policy is enforced using separate, physical assemblies which communicate with each-other via dependency-inversion with interfaces.
    • Presentation and business logic layers are "data-layer agnostic" as much as reasonably possible.  Like the previous point, this is more for testability than it is for the expectation that the data-layer will be actually switched out at a later time.  The phrase "reasonably possible" is mentioned because there is often an unavoidable amount of implicit, data-layer assumptions built into both the presentation and business logic layers.  For example, if the data-layer uses proxies to watch for an "is-dirty" state, as NHibernate does, then the business layer need not concern itself with these details; but switching to a less-autonomous data-layer may force the business layer to take on this responsibility.  Certainly, with enough effort, the business layer could become completely data-layer agnostic; but in most cases, the extra effort isn't worth the added cost of premature generalization.
    • NHibernate is used as the data-layer ORM.  A data-access object (DAO) abstract factory pattern is employed to easily switch between production and "mock" DAOs for unit-testing. 
    • Model-View-Presenter (MVP) is optionally employed to keep code-behind pages as part of the view, pure and simple.  MVP is the simplest solution I have found for making ASP.NET code-behind logic more maintainable and testable.  But MVP comes with a cost - it adds another layer of indirection and complexity to the application; therefore, the "Presenters" layer (the "P" in MVP) may be considered as an optional piece to the suggested architecture.  Furthermore, the benefits of MVP may be employed later in the project life-cycle, when warranted, without having to modify the existing presentation layer.  (Martin Fowler has suggested that MVP be split into Supervising Controller and Passive View.  What's described below is consistent with Supervising Controller.)

    In a Nutshell

    Below is a graphical summary of the architecture.

    Application Architecture

    In the above diagram, each raised box represents a distinct specialization of the application. Each gray box then represents a separate, physical assembly; e.g. MyProject.Web.dll, MyProject.Presenters.dll, MyProject.Core.dll, etc. The arrows represent assembly dependencies. For example, the .Web assembly depends on the .Presenters and .Core assemblies.

    The assemblies avoid bi-directional dependency using the techniques "Dependency Inversion" and "Dependency Injection."  ("DI" in the diagram should be read as "dependency injection.")  To illustrate, note that the .Core assembly contains, along with domain objects, the DAO interfaces.  The .Data assembly contains classes which inherit from these interfaces to define the DAO implementations.  The .Core assembly is then given its DAO dependencies from another layer, such as from .Presenters or .Tests.  Furthermore, another "service layer" could be employed to centralize the DAO-creation services.  (Martin Fowler discusses the service-layer approach in Patterns of Enterprise Application Architecture.)  One approach that I've had success with is leveraging the Castle Windsor project to inject DAO dependencies.  Note that this third party tool adds another layer of complexity to the application and should be carefully considered before use (aka "happy fun ball").

    Implementation Details

    In all seriousness, an entire book could be written to describe the preceding diagram in full detail.  What follows are a number of articles which explain the architecture in greater depth.  (Warning:  utterly shameless plugs for articles I've written!)

    Dependency Injection for Loose Couplinghttp://www.codeproject.com/cs/design/DependencyInjection.asp.  As mentioned previously, the architecture uses dependency injection (DI) throughout the application to keep the application layers loosely coupled.  This article offers a simplified overview of the technique - it assumes DI is being performed from one layer to another layer.  For a more complete discussion of Dependency Injection, or more cryptically called "Inversion of Control," be sure to read Martin Fowler's article on the subject.  Fowler's article also goes into greater depth of using DI "containers."

    NHibernate Best Practices with ASP.NEThttp://www.codeproject.com/aspnet/NHibernateBestPractices.asp.  This audaciously named article gives a good overview of the abstract data-access-object factory used within the architecture and how it's used with test-driven development.  This article includes many details of the suggested architecture, sans the inclusion of MVP and Castle Windsor.

    Using NHibernate with Multiple Databaseshttp://www.codeproject.com/useritems/NHibernateMultipleDBs.asp.  If your project requires communications with multiple databases, then this article provides an extension to the previous NHibernate article.  There is very little, published content concerning this subject and I am open to hearing alternative approaches.

    Model-View-Presenter with ASP.NEThttp://www.codeproject.com/aspnet/ModelViewPresenter.asp.  There are many resources available for learning about MVP; the emphasis here is with ASP.NET and a variant I call "User-Control as View."  The Model-View-Presenter pattern may be employed in the architecture to allow code to be unit-tested that would usually have been found in the code-behind pages.  The downloadable sample “MVP Enterprise Solution,” found within the article, includes a working example of using the Castle Windsor project within ASP.NET.  As noted previously, both MVP and the Castle Windsor project add additional layers of complexity to the application and should only be employed if their benefits of maintainability and testability are warranted in your environment.

    Parting Thoughts

    There is no single best-practice for architecting ASP.NET, web applications; but, after taking described assumptions into account, what I've described may serve as a solid, default architecture for future project work.  At the very least, it provides a pool of ideas for consideration.  As always, I'm open to thoughts, rebuttals, criticisms and suggestions and welcome your comments.

    Billy

More Posts

Our Sponsors

Proudly Partnered With