Microsoft’s LINQ to SQL is a great choice for module development on the DotNetNuke platform. It allows for rapid development, is well-suited to smaller and focused architectures, and has a lightweight footprint. For many DotNetNuke modules – which often focus on performing one highly-focused task – this is a natural fit.
In this article we explore the many advantages of using LINQ to SQL as a data tier within a DotNetNuke module, discuss the alternatives, and demonstrate a sample module using this technology.
LINQ to SQL is a great choice for module development in the DotNetNuke platform.
LINQ to SQL for Rapid Development
LINQ to SQL is a lightweight pseudo-ORM tool allowing for rapid development in connected, highly-focused architectures. It is a Microsoft SQL Server-specific technology. LINQ to SQL entities are easily updated as the underlying schema changes. Overall, its lightweight implementation offers “just enough” abstraction for such smaller, focused applications.
LINQ to SQL’s lightweight implementation offers “just enough” abstraction for smaller, focused applications.
Saliently, because DotNetNuke is predominately operated using Microsoft SQL Server, a more robust platform such as the Entity Framework (operable against a wide variety of data stores) introduces additional unnecessary overhead. Similarly, for most DotNetNuke modules, the database model is generally equivalent to its final conceptual structure. Such a module does not require the additional overhead (present in other ORMs such as the Entity Framework) that allows such separation.
Isn’t LINQ to SQL Deprecated?
No. It is true that LINQ to SQL was recently transferred to the SQL Data Programmability Team (home of the Entity Framework). There, Program Manager Tim Mallalieu has clearly communicated that LINQ to SQL is alive, well, and will be supported into .NET 4.0 as it is merged into the Entity Framework (Schwartz, 2008). The bottom line remains that it is both safe and prudent to move forward with LINQ to SQL development.
LINQ to SQL is alive, well, and will be supported into .NET 4.0
Why not the DAL?
It is worth discussing why LINQ to SQL might be used in favor of the DotNetNuke-recommended data-layer solution, the Data Access Layer (DAL) and subsequently released DAL+. Both are designed to target any backing store (through the use of an abstract provider pattern). Access is generally achieved through the retrieval of IDataReader -implementing objects from the data tier. However, in practice, DotNetNuke is virtually always deployed using Microsoft SQL Server (Leupold, 2008). Given this reality, the DAL abstract provider pattern adds additional complexity with little marginal utility.
LINQ to SQL avoids many of these drawbacks given the context of a focused, non-enterprise module. Object exchange across tiers involves strongly-typed entity objects (instead of weakly-typed IDataReader-implementing property bags). Hydration of distinct business entities from the already strongly-typed LINQ to SQL objects thereby becomes optional (and in many applications unnecessary). Finally, LINQ to SQL provides a footprint that is similar to or less than (when it is allowed to generate dynamic SQL) its DAL counterpart.
A Drawback: Cross-Tier and Entity Context Lifetime
There arguably exist some design disadvantages associated with the use of LINQ to SQL entity objects as an unmediated data layer. While such architectural caveats are generally beyond the scope of this article, it is worth mentioning that Microsoft LINQ Program Manager Dinesh Kulkarni (2007) noted that there exists no out-of-the-box multi-tier story within the LINQ to SQL framework. This, inter alia, makes change-tracking across tiers within LINQ to SQL particularly difficult. This difficulty, however, is offset to some length by the rapid, focused design constraints discussed above.
In a stateless, web-oriented environment, this issue is of particular relevance with data context lifetime. LINQ to SQL requires all operations to be performed against a DataContext object, which is responsible for differential tracking. This context must, then, exist throughout a “unit of work” – which, for module development purposes is (in general) equivalent to the lifetime of any given ASP.NET request thread.
One common solution to this problem involves the implementation of the Unit of Work (UoW) pattern (Fowler, 2002). This pattern is used in other ORM solutions such as NHibernate. A straightforward implementation utilizes the HttpContext.Current.Items collection to store a context over the lifetime of a request. This approach is demonstrated in listing 1, and is used for the DotNetNuke module demonstration that follows. This approach may be improved through the application of an Inversion of Control (IoC) pattern (to avoid the System.Web reference in the data tier), but such an enhancement is beyond the scope of this article (Johnson & Foote, 1988).
static class Context
{
private const string key = "MyDataContext";
public static MyContext Current
{
get
{
if (!HttpContext.Current.Items.Contains(key))
HttpContext.Current.Items.Add(key,
new MyContext(Config.GetConnectionString()));
return (MyContext)HttpContext.Current.Items[key];
}
}
}
Listing 1: Unit of Work pattern for handling a LINQ to SQL data context
LINQ to SQL in Action: A Sample Module
A Search and Replace DotNetNuke Module
We now turn to a concrete example demonstrating the use of LINQ to SQL in a DotNetNuke module. This module is designed to search and replace text across all instances of Text/HTML modules in a given DotNetNuke website. The module is developed using the web application project type (WAP) generally (but not exclusively) preferred by DotNetNuke developers.
Note that, for purposes of brevity, we perform business-related functionality directly within the user control event handler and embed the LINQ to SQL entities and context directly within the UI assembly. While this allows for a more straightforward demonstration, any robust solution would certainly further separate these distinct architectural concerns.
This module was tested against and deployed within DotNetNuke version 4.91 and 5.0. It assumes that ASP.NET 3.5 is deployed in the server environment (required for use of LINQ to SQL). Note that DotNetNuke now 5.0 supports auto-configuration of ASP.NET 3.5 through its UI.
Project Structure and Discussion
The module project structure contains three elements relevant to this discussion: a user control (and associated code-behind), a UoW context class (discussed above), and a LINQ to SQL database meta-model. The project also contains a module schema file (SearchAndReplace.dnn) used to install the module within a particular DotNetNuke installation. Figure 1 depicts the project structure as displayed in the Visual Studio solution explorer.

Fig. 1: Project structure in Visual Studio Solution Explorer
LINQ to SQL Model
For purposes of simplicity, our model uses tables and views that exist across all DotNetNuke installations. This alleviates the need to create additional database objects during module installation. Note, however, that these techniques may be utilized against any custom database schema. Consult the DotNetNuke module development documentation (Washington, 2007) for more information about the creation and population of custom database objects during module installation.
The entity model in this project contains two entities, as illustrated in figure 2. The first, HtmlInstance, contains the raw HTML data we desire to search (and replace). Because DotNetNuke identifies a given website by its unique portal identifier (many such portals may exist within a given installation), we must associate this entity to something that contains the needed value. In this case we use a second entity, Module, which contains the desired identifier. A custom association (keyed on ModuleId) joins the two entities and allows parent and child references.

Fig. 2: LINQ to SQL Entity Model
Sample Project Markup and Code
Our markup, located in SearchAndReplace.ascx, is straightforward and requires little discussion. This markup is displayed in listing 2.
<%@ Control Language="C#"
Inherits="SearchAndReplace.Presentation.View" %>
<div>
Search and replace text in all Text/HTML modules
</div>
<div>
Search for:
<asp:TextBox ID="SearchFor" runat="server" />
</div>
<div>
Replace with:
<asp:TextBox ID="ReplaceWith" runat="server" />
</div>
<asp:Button Text="Submit" runat="server"
OnClick="SearchAndReplace_Click" />
Listing 2: Markup within SearchAndReplace.ascx module user control
Business Logic and Code-Behind
The code-behind for our module, SearchAndReplace.ascx.cs, contains the code (listing 3) used to interface with the LINQ to SQL entity model discussed above. The first statement (lines 1–3) queries the data model for a set of HTML data instances, and is constrained by the current portal identifier (line 3). This is necessary because DotNetNuke supports multiple websites within the same installation, making it essential to ensure that the module only operates on the “current” website (as identified by this.PortalID). Next, the resultant entity enumeration is walked, during which string replacement is performed via a call to string.Replace (lines 5–7). Finally, the updates are committed (line 9). Note the use of the UoW-inspired Data.Context.Current instance throughout the method body. Additionally, despite the fact that an assignment is made to ALL entities (even those where no replacement is actually made), LINQ to SQL tracks and updates only those entities that were actually modified.
1: var htmlModules = Data.Context.Current.HtmlInstances
2: .Where(html =>
3: html.Module.PortalID == this.PortalId);
4:
5: foreach (var htmlModule in htmlModules)
6: htmlModule.DesktopHtml = htmlModule.DesktopHtml
7: .Replace(SearchFor.Text, ReplaceWith.Text);
8:
9: Data.Context.Current.SubmitChanges();
Listing 3: Body of the SearchAndReplace_Click event handler in SearchAndReplace.ascx.cs
Demonstrating the Sample Module
The compiled module files may be zipped, uploaded to an active DotNetNuke installation, and added to a new page within DotNetNuke*. The module will render in a manner similar to that depicted in figure 3.
For demonstrative purposes, we will replace all instances of the word “DotNetNuke” with the replacement “DotNetNuke with LINQ to SQL.” In a freshly-installed DotNetNuke 5.0 site, this will result in changes to three module instances. Figures 4 and 5, respectively, display one such section both before and after the changes.

Fig. 3: Display of Sample LINQ to SQL Module

Fig. 4: Before Replacement

Fig. 5: After Replacement
Important: This module is intended as a LINQ to SQL sample for demonstrative purposes only. Because the module has the potential to affect markup across an entire DotNetNuke website, please ensure that only administrative users have access to its functionality! Figure 6 illustrates the recommended permissions.

Fig. 6: Recommended Permissions – Deny on All Users
A Note about Database Owners and Object-Qualifiers
DotNetNuke allows an installation to be configured with a custom database owner and object qualifier (the latter being applied as a prefix on all database objects within a particular installation). This allows for myriad hosting configurations, including shared servers and multiple, isolated DotNetNuke installations within a database (each with a unique object qualifier). Additionally, the use of non-default values for these attributes yields some protection against automated attacks (Connolly, 2006).
An installation using non-default database owner and/or object qualifier introduces some difficulties when using LINQ to SQL. For those modules that must accommodate such scenarios – including all modules developed for commercial use – an alternative now exists in the form of a model adapter (Haynes, 2008). This adapter analyzes a LINQ to SQL meta-model at runtime and dynamically produces an adapted model compatible with any installation (regardless of database owner and object qualifier specification). It is available free of charge and under a liberal BSD license at http://codeplex.com/DNNLinqToSqlAdapter.
The Bottom Line
LINQ to SQL is not the panacea for the data tier of all DotNetNuke modules; no approach can be universally assigned such an accolade. Each project must carefully balance development complexity, level of abstraction, database targeting flexibility, performance, and many other factors. For modules requiring rapid development, performing a straightforward and focused task, and not requiring database agnosticism, LINQ to SQL remains an excellent choice. Strongly consider it for your next DotNetNuke module project.
References
- Connolly, C. (2006). Securing DotNetNuke: Hardening DotNetNuke Installations. Retrieved Dec 2008, from http://dotnetnuke.com/LinkClick.aspx?fileticket=qkVjRRDHNwU%3D
- Fowler, M. (2002). Patterns of Enterprise Application Architecture. Boston, MA: Addison-Wesley Longman Publishing Co.
- Haynes, B. (2008). DotNetNuke LINQ to SQL Model Adapter. Retrieved Dec 2008, Web site: http://codeplex.com/DNNLinqToSqlAdapter
- Johnson, R., & Foote, B. (1988). Designing Reusable Classes. Journal of Object-Oriented Programming. 1, 22-35.
- Kulkarni, D. (2007). LINQ to SQL: What is NOT in RTM (V1). Dinesh's Cyberstation. Retrieved Dec, 2008 from http://blogs.msdn.com/dinesh.kulkarni/archive/2007/10/15/linq-to-sql-what-is-not-in-rtm-v1.aspx
- Leupold, S. (2008). Re: MySQL 5x and DotNetNuke 4.7x. Retrieved Dec 2008, from http://dotnetnuke.com/Default.aspx?ThreadId=223520&Scope=Posts&TabId=795
- Schwartz, J. (2008). Microsoft Says LINQ to SQL Not Dead. Redmond Developer News: Data Driver. Retrieved Dec 2008, from http://reddevnews.com/blogs/weblog.aspx?blog=3036
- Washington, M. (2007). DotNetNuke 4.0 Module Developers Guide (Part 1). Retrieved Dec 2008, from http://dotnetnuke.com/LinkClick.aspx?fileticket=s%2bGtSX0BJTM%3d
De sources die bij dit artikel horen kun je downloaden via Haynes_Linq2SqlAndDNN_SRC.zip en de installatie-bestanden via Haynes_Linq2SqlAndDNN_INST.zip.