Building Layered Web Applications with Microsoft ASP.NET 2.0 - Part 1


NOTE: the concepts presented in this article are now considered obsolete possibly because better alternatives are available.

Update!! - I have written a new series on N-Layer design targeting ASP.NET 4.5 and Entity Framework 5. You can check out the new series here.

Update!! 12-24-2008 - I have written a new series on N-Layer design as a major follow up to this one. It builds on the foundation created in this first series, but digs much deeper into concepts like Validation, Sorting, Paging, Concurrency and Security. You can check out the new series here.

Update!! 04-25-2007 - There is now also a VB.NET version of the code available for download. You find the download at the end of this article. For more information about the translation, check out this blog post.

This is part 1 of the article series "Building Layered Web Applications" that shows you how to build N-Layer applications with Microsoft ASP.NET 2.0. These articles teach you how to design, build and use custom business objects in your web application. The target audience for this series are developers that are ready to make the switch from using SqlDataSource controls to ObjectDataSource controls with custom business objects. Experience with ASP.NET 2 and C# is necessary while some knowledge about object oriented design certainly helps. The design I am going to show you in these articles is a simplified version of a design you would use in a real world application. It doesn't feature all the necessary functionality your application needs, but instead focuses on the underlying concepts.

What's important to realize is that this is *my* take at layered design for web applications. I won't say this is *the* design for the problem, or the only right one. In fact, I am sure some will judge this as "not the right one". However, it's a design that has worked for me in the past and still works today. It works best in many day-to-day small to medium sized web sites. You know, the kind of sites many of you (including myself) are building right now.

Part one deals with the design of the application: what business objects do you need to fulfill the requirements of the application? What should these objects be capable of and how do they look? How do these business objects interact with other parts of the system? Part two then shows you how to implement the code for these objects, while part three deals with using the business objects in a real-world web application.

The entire series (including this current article) can be found here:

The article uses a SQL Server 2005 Express database which is easy to use in development scenario's. However, the downloads for this series also come with the T-SQL scripts to recreate the database in SQL Server 2000 or SQL Server 2005. You'll find the download link at the end of this article. Besides the forementioned SQL scripts and database, the download also contains the full source for the demo application in C#.

Introduction

Layered development or multi-layer development refers to a development model where presentation, business logic and data are separated. This brings many advantages, including cleaner code, increased maintainability and the ability to spread your application's load over multiple servers. In the discussion of layered design, you often see both the terms layer and tier. Generally, layer refers to a conceptual separation of the application, while tier defines physical boundaries. This article talks mainly about layers and presents a design where quite often most layers run on the same physical system, with some of them even in the same process space.

To get a general understanding of what a multi layered application looks like, consider the following diagram that shows a number of possible layers in a system.

Overview of Different Layers in a System
Figure 1 - Overview of the Different Layers in a System

This diagram describes a general process of an application that presents data that comes from a database. The application, like a web site or a Windows Forms application is usually called the Presentation layer. Then in the middle, you find the Business Logic Layer, or the BLL that is the bridge between the Presentation layer and the next layer: the Data Access Layer or the DAL. This DAL then talks to the database to perform selects, inserts, updates and deletes.

One of the ideas of this design is that you can replace one or more of the layers without affecting the others. So, you could for example drop the web site as the presentation layer and replace it with a Windows Forms application. This change wouldn't require a change in any of the other layers. Similarly, you should be able to remove a SQL Server specific DAL and replace it with an Oracle or Microsoft Access version without the Presentation layer even noticing the difference.

In the diagram in figure 1 you see a process go around in a counter clockwise direction. The process goes through the following 6 steps:

  1. The Presentation layer asks the BLL for some object, for example a contact person.
  2. The BLL can optionally perform some validation (for example, is the current user allowed to make this call?) and then forwards the request to the DAL.
  3. The DAL connects to the database and asks it for a specific record.
  4. When the record is found, it is returned from the database to the DAL.
  5. The DAL wraps the database data in a custom object and returns it to the BLL.
  6. Finally, the BLL returns the object to the Presentation layer, where it could be displayed on a web page for example.

I'll revisit this diagram at the end of the article and add more detail to it.

Starting with ASP.NET 1.0, layered development was brought to web applications on the Microsoft platform. While previous versions of ASP (now referred to as "classic ASP") allowed for some separation in the form of COM components or ASP classes, this usually wasn't done as it was quite cumbersome and hard to maintain. However, with ASP.NET it's much easier to create reusable, object oriented classes that can be consumed by web applications and other types of applications. It's easy to create classes in a separate class library (or in the App_Code folder - new to ASP.NET 2) and then reference these classes in your web application.

In this article series I'll show you how to design, build and implement reusable object oriented classes that are easy to use and maintain. The objects created from these classes are often referred to as business objects so that's the term I'll use in these articles. Throughout the articles, I'll use a simple and straight forward sample application that allows you to manage your contact persons and their contact data, like e-mail addresses and phone numbers.

Different Options for Building Database Driven Web Sites

Before we dig deeper in the world of custom business objects, let's briefly go over a couple of very common examples that are used nowadays to create database driven web applications in ASP.NET 2.0. I'll take the Edit page for a Person (shown in Figure 3) as an example when looking at all the options.

The Spaghetti Model

This model has a lot of similarities with the way classic ASP sites were built. All the data access code and business logic is placed in the presentation layer; with either in-line code, or in the code behind of the ASPX page. For example, on a page to edit contact persons, in Page_Load you open a connection object, and then based on the value of the query string for example, you get a SqlDataReader and then use that to fill a number of TextBox controls on your page. When the user clicks the Save button, you get the data from the TextBox controls, construct your own SQL statement to update the database and send that over an open connection.

protected void Page_Load(object sender, EventArgs e)
{
  if (!Page.IsPostBack)
  {
    string sql = @"SELECT FirstName, LastName, 
        MiddleName FROM ContactPerson WHERE Id = 1";

    using (SqlConnection myConnection =
        new SqlConnection(ConfigurationManager.ConnectionStrings["NLayer"]
        .ConnectionString))
    {
      using (SqlCommand myCommand = new SqlCommand(sql, myConnection))
      {
        myConnection.Open();
        using (SqlDataReader myReader = myCommand.ExecuteReader())
        {
          if (myReader.Read())
          {
            txtFirstName.Text = myReader.GetString(0);
            txtLastName.Text = myReader.GetString(1);
            if (!myReader.IsDBNull(2))
            {
              txtMiddleName.Text = myReader.GetString(2);
            }
          }
          myReader.Close();
        }
        myConnection.Close();
      }
    }
  }
}

protected void btnSave_Click(object sender, EventArgs e)
{
  string sqlBase = @"UPDATE ContactPerson SET FirstName='{0}',
  LastName='{1}', MiddleName ='{2}' WHERE Id = 1";
  using (SqlConnection myConnection =
        new SqlConnection(ConfigurationManager.ConnectionStrings["NLayer"]
            .ConnectionString))
  {
    string sql = String.Format(sqlBase, 
           txtFirstName.Text, txtLastName.Text, txtMiddleName.Text);
    SqlCommand myCommand = new SqlCommand(sql, myConnection);
    myConnection.Open();
    myCommand.ExecuteNonQuery();
    myConnection.Close();
  }
}

While this code certainly works, it has a number of serious issues.

  1. This code is open for SQL injection. It's easy for a malicious user to enter data in one of the TextBox controls to completely change the meaning of the SQL statement. That way, a user could delete a record (or the entire database), instead of updating one specific record.
  2. This code is difficult to write and remember. You hardly get IntelliSense with this code, especially not with column names. Every time you want to display someone's LastName, you need to remember you queried it as the 2nd column in the SQL statement.
  3. You cannot reuse this code. On every page where you want to let a user edit a contact person record, you need to copy and paste this code. If you want to change something - say you want to add an additional field to the ContactPerson table, you'll have to change multiple pages. The same applies to fixing bugs; if you know this code has a bug, you need to change it in multiple locations.

SqlDataSource Controls

Another common option is the use of SqlDataSource controls. These controls connect to the database for all CRUD (Create, Read, Update and Delete actions) and offer the data to other controls like the GridView, FormView and so on.

While they are easy to configure using the Configure Data Source wizard, SqlDataSource controls often require large amounts of code in your page. As an example, here's a SqlDataSource control that is capable of selecting, inserting, delete and updating a ContactPerson in the database.

<asp:SqlDataSource 
ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:NLayer %>"
DeleteCommand="DELETE FROM [ContactPerson] WHERE [Id] = @original_Id"
InsertCommand="INSERT INTO [ContactPerson] ([FirstName], [MiddleName], [LastName], [DateOfBirth], [ContactPersonType]) VALUES (@FirstName, @MiddleName, @LastName, @DateOfBirth, @ContactPersonType)"
SelectCommand="SELECT * FROM [ContactPerson]"
UpdateCommand="UPDATE [ContactPerson] SET [FirstName] = @FirstName, [MiddleName] = @MiddleName, [LastName] = @LastName, [DateOfBirth] = @DateOfBirth, [ContactPersonType] = @ContactPersonType WHERE [Id] = @original_Id"
OldValuesParameterFormatString="original_{0}" > <DeleteParameters>
<asp:Parameter Name="original_Id" Type="Int32" />
</DeleteParameters>
<UpdateParameters>
<asp:Parameter Name="FirstName" Type="String" />
<asp:Parameter Name="MiddleName" Type="String" />
<asp:Parameter Name="LastName" Type="String" />
<asp:Parameter Name="DateOfBirth" Type="DateTime" />
<asp:Parameter Name="ContactPersonType" Type="Int32" />
<asp:Parameter Name="original_Id" Type="Int32" />
</UpdateParameters>
<InsertParameters>
<asp:Parameter Name="FirstName" Type="String" />
<asp:Parameter Name="MiddleName" Type="String" />
<asp:Parameter Name="LastName" Type="String" />
<asp:Parameter Name="DateOfBirth" Type="DateTime" />
<asp:Parameter Name="ContactPersonType" Type="Int32" />
</InsertParameters>
</asp:SqlDataSource>

Not only do you get a lot of code, the worst part is that this code is embedded directly in your page. If you want to list a contact person on two different pages, you need to recreate this code on both. If you need to make a change because, say, you want to add an additional field, you need to update all pages that reference this table. You can decrease the problem a little by using stored procedures, but you still need to set up all the code for the parameters.

TableAdapters

Another alternative worth looking at are TableAdapters. In short, a TableAdapter is a class that inherits from System.ComponentModel.Component and that handles all the interaction with the database. The good thing about TableAdapters is that they can be created automatically by Visual Studio. Based on a simple select statement, it generates code that handles inserts, updates, selects and deletes for you. As the business object, you get classes that inherit from System.Data.DataTable and System.Data.DataRow which have convenient methods like AcceptChanges to send any changes to your business object to the database.

For a great tutorial on TableAdapters, refer to Scott Mitchell's 3-Tier Architecture tutorial series on the official ASP.NET web site.

Personally, I am not too fond of TableAdapters. First of all, a lot of code gets generated that you can't really look into or change. Also, a lot of data is stored in XML files in a custom format, so it can be hard to use them in conjunction with (custom) code generators. But in my opinion the biggest drawback is how validation is handled. Since you have no direct access to properties of the object, like ContactPerson.FirstName, you have to handle the ColumnChanging event of the DataTable object, validate your columns and optionally throw and exception when the data is in an invalid format. This can make the code look a little awkward and may make it difficult to maintain.

Finally, because so much code is generated for you, it's difficult to create specialized classes to get a clean object model.

So, although they're often quick to use in many situations, I don't use them very often. Your mileage may vary and you may have a different opinion about how they work, so be sure to check out the tutorial series by Scott Mitchell to see if TableAdapters are useful to you.

Linq and Linq for SQL

Another very promising option is Linq. In short, Linq is "a collection of features that help compilers understand and implement query logic over in-memory collections of objects". One of the components of Linq, called Linq for SQL, "provides a run-time infrastructure for managing relational data as objects without giving up the ability to query. It does this by translating language-integrated queries into SQL for execution by the database and then translating the tabular results back into objects you define." This way, Linq for SQL can handle most of the database interaction for you. However, since Linq is still in beta, and will be for some time, it isn't always applicable in applications you build today. For more information about Linq and Linq for SQL, check out the Linq Project homepage.

Custom Business Objects

With the alternatives behind our back, let's take a look at custom business objects. In many cases, a business object is a simple class that inherits from Object and optionally implements one or more interfaces to make it easy to pass the object around. In its simplest form, a custom object can look like this:

public class ContactPerson
{
  private string firstName;
  public string FirstName
  {
    get { return firstName; }
    set { firstName = value; }
  }  
}		  

In practice, this object on its own isn't very useful, as it can only hold data but not perform any operations. However, before we look at that in more detail, we first need to look at the design of our objects. How do we want our objects to look? What data should they contain? What operations must they support? All these questions are generally answered in the requirements gathering phase.

Throughout the series, I'll use a small sample application that allows you to manage contact persons and their addresses, phone numbers and e-mail addresses. I'll generally refer to the latter three as contact records, or contact data. The object model for the application will have the ContactPerson as a root object, containing collections with the contact data.

Introduction to the Sample Application

The Contact Person Manager application is a simple web based application that allows you to manage contact persons and their associated contact data, like e-mail addresses and phone numbers. The application allows you to create new, and update and delete existing contact persons. In addition, it allows you to manage the associated contact data for each contact person as well.

The following screen shot shows a list with all the contact persons in the system.

A List of Contact Persons
Figure 2 - A List of Contact Persons

Clicking the Edit link for a person takes you to a page where you can edit the details for the contact person:

Editing a Contact Person
Figure 3 - Editing a Contact Person

The Delete link in Figure 2 allows you to remove the contact person, together with all of its contact records.

When you click one of the contact records links you see in Figure 2, like Addresses, you see a list of address records for the requested person that are editable as well:

A List of Addresses for the Contact Person
Figure 4 - A List of Addresses for the Contact Person

During the remainder of these articles, you'll see how the entire application is built, starting with the design all the way through building the UI.

Design - Gathering Requirements

Before you start building an object, you need to gather the requirements for that object. Note that this isn't a one-time operation. It's not uncommon to revisit your design multiple times during the development of an application, because requirements have changed.

There are a few ways to gather requirements for an application, including data analysis and data flow, UI design and story boarding and Business concept and process analysis [*]. The actual details of these methods is a little outside the scope of this article, but let's assume we've held a meeting with one of the core stakeholders of the application that has been able to describe what it is she wants the ContactPerson manger application to do:

[*] Taken from Expert C# 2005 Business Objects by Rockford Lhotka, page 322.

  • The user of the application must be able to view a list of all contact persons in the system. Additionally, she should be able to create new, and change and delete existing contact persons.
  • The user of the application must be able to select a specific contact person, and then get a list of its associated addresses. In addition, she should be able to create new and change and delete existing addresses for the contact person.
  • The user of the application must be able to select a specific contact person, and then get a list of its associated e-mail addresses. In addition, she should be able to create new and change and delete existing e-mail addresses for the contact person.
  • The user of the application must be able to select a specific contact person, and then get a list of its associated phone numbers. In addition, she should be able to create new and change and delete existing phone numbers for the contact person.

From this simple list, you could list the following classes that you need in your application:

  • ContactPerson
  • Address
  • EmailAddress
  • PhoneNumber

Besides these actions, you should also think about the data that you want these objects to store. A good way to gather this information is sketching it out on a whiteboard, writing down whatever you think is appropriate for the application. After a white-board session, you may come up with the following diagram:

A First Attempt to the Class Design for the ContactPerson Application
Figure 5 - A First Attempt to the Class Design for the ContactPerson Application

In this diagram, you see a simple ContactPerson class with a number of obvious properties, like FirstName, LastName and so on. You also see the contact data, like Address and PhoneNumber. You can see that behind these classes, you see more of them, implying that a ContactPerson can have more than Address, EmailAddress and PhoneNumber. This is an indication that your application might need to present those classes in the form of collections. You'll see how these collections are designed later in this and the next article.

The next step to think about are the actions that your business objects should be able to carry out. First, you need to determine where you want to store your behavior. You can decide to put all the method logic in the class itself, making them smart classes. Alternatively, you could decide to store only data in the actual class (a dumb data class) and then create a separate class to handle all interactions with your data class. In the first example, all you need is a ContactPerson class, with both properties and methods.

In the second example, you could have a simple ContactPerson class with only properties, and a separate ContactPersonManager class that is responsible for working with instances of ContactPerson. The biggest benefit of this design is the way your other layers can work with these objects. When you define a separate data object, both your Business Layer and the Data Access Layer can reference it and thus use it. This makes it much easier to pass instances of your business objects around.

For the sample application, I'll use "dumb" classes that only store data. Examples are the ContactPerson and Address classes. I'll then use a second set of classes whose names end in Manager. So, I have an AddressManager to manage Address instances, a ContactPersonManager to manage ContactPerson objects and so on. These Manager classes in turn talk to the data access layer, passing around instances of ContactPerson, Address and so on.

Let's take ContactPerson and its associated ContactPersonManager class as an example. To be able to display a list of contact persons, select one to edit or delete it and to create an entirely new contact person, you could come up with the following methods:

  • GetItem
  • GetList
  • Insert
  • Update
  • Delete

If you're familiar with databases, you may recognize the CRUD acronym here: Create, Read, Update and Delete where the GetItem and GetList methods read the data for a single object or a list of objects respectively. In addition to these five methods (which are shared across many business objects) you could also come up with other methods like:

  • Search
  • Deactivate
  • Clone
  • Filter

These methods are often more specific to the business object. In the sample application, I'll stick to the methods from the first list, but you can use the exact same principles to implement other methods in your custom objects.

Design - Designing your Object Model

Now that we have a list with requirements, it's time to design the actual classes. There are many design tools available to help you in this process. You can use the Class Designer of Visual Studio 2005 (available in all versions except the Express Editions), Microsoft Visio or a number of other commercially available modeling tools. For this article, I'll stick to Visual Studio's Class Designer. The biggest benefit of this tool is that the design of your classes is always in sync with your code and vice versa. So, whenever you add, say, a property to one of your classes, it shows up automatically in the diagram. The reverse is also true; when you add a method in the diagram, the method's signature is added to the code for you. For some tutorials about using the class designer, check out the following links:

So, let's take a look at the first draft of the class design for the demo application based on the white board sketch you saw before:

First Draft of the Class Diagram of the ContactPerson Application
Figure 6 - The First Draft of the Class Diagram

This diagram displays a number of classes and enumeration types that make up the object model for the Contact Person Manager application. There are a few things worth noting.

First of all, you can see the diagram shows "smart " classes, where the data and the operations to work with that data are located in the same class. However, I decided to use "dumb objects" with separate Manager classes instead, so we'll need to change this in the next round.

Next, you can see I added two enumerations called ContactType and PersonType. The enumerations are used to determine the type of the contact person or contact record. So, a contact person can either be a friend, a family member or a colleague. You can change or add PersonType elements in the PersonType.cs file in the Enums folder. Similarly, ContactType is used to determine whether a contact record holds personal or business data.

Another thing to notice is that the Address class is missing a Type property; something we overlooked in the requirements gathering phase. This property needs to be added during the second round of class design.

The Address, PhoneNumber and EmailAddress classes are all lacking methods to get data in and out of the database. These methods will need be added in separate classes in the next round as well.

Another shortcoming of the design is the fact that ContactPerson has no properties that refer to the EmailAddress, Address or PhoneNumber classes. Obviously, it would be convenient to have those types available in the form of a collection. To do this, we can implement the collections as a generics List<T> type where T refers to the generic type like Address (List<Address>), PhoneNumber (List<PhoneNumber>) and so on. To make it easier for developers that are unfamiliar with generics to work with these kind of collections, I'll create four collections, like EmailAddressList, ContactPersonList and so on, that inherit from their generic counterpart (e.g. List<ContactPerson>. In the next part of this article series, you'll see how these lists are implemented.

To make it easier to display the full name of a contact person, a FullName property on this class would be nice. That way, client code doesn't have to mess with concatenating the first and last, and optionally the middle name every time it needs to display the contact person's name, but can instead use the FullName property directly. This property will be implemented as read-only and will return the concatenated values of the three name properties.

The final thing to notice is the Update and Insert methods of the ContactPerson class. Both methods perform a very similar function in that they save the data for the ContactPerson in the underlying data store. From an API perspective, it would be easier to call this method Save and then let the business object determine whether to insert a new contact person in the database, or to update an existing one. This concept is often referred to as Upsert, a combination of the words Insert and Update.

With all those changes applied, the class diagram for the data objects now looks like this:

The Second Version of the Class Diagram
Figure 7 - The Second Draft of the Class Diagram Showing the Data Objects

In the upper left corner, you see the four main Business Objects. Notice how ContactPerson now has properties to hold collections of the other types: Addresses, EmailAddresses and PhoneNumbers respectively. Each of these types is of the type of its respective collection you see in the lower half of the image: AddressList, EmailAddressList and PhoneNumberList. To work with lists of contact persons, the application also has a ContactPersonList.

Finally, I added a NotSet value to both enumeration so they can hold undetermined values.

To work with these classes in the system, each class gets an associated *Manager class, shown in the following figure:

The *Manager Classes
Figure 8 - The *Manager Classes

Although not visible in this diagram, each of the classes has a reference to the business objects namespace you saw in Figure 7, so each class knows how to deal with instances of those business objects. You'll see how this work in part two of the article series.

The implementation of these classes is pretty straight forward: GetItem returns an instance of the class, GetList returns a list of instances of the class, while Save accepts an instance of the class that is to be saved in the database. Finally, the Delete method accepts an instance of the class as well, containing the item that should be deleted.

GetItem for the ContactPersonManager has an overload that allows you to determine whether you want to load only the basic data for a ContactPerson, or all it associated contact data as well.

Another interesting thing to look at is the implementation of the GetList methods in the EmailAddress, Address and PhoneNumber classes. Since each of those objects belongs to a specific ContactPerson, the GetList methods expects the ID of a contact person. That way, GetList knows for what person it must retrieve the records. Again, you'll see how this works later on.

Design - Designing the Data Access Layer

The next step in the design process is the design of a Data Access Layer, often referred to as the DAL. You have a couple of options to design your DAL.

TableAdapters

Earlier in this article I talked about TableAdapters as the representation of your business objects. Personally, I don't like them as business objects as I find them too close to the data, and too far away from the business domain. However, as a Data Access Layer, they may make a lot of sense. Calling code (the presentation layer) calls a method on the business object, like Save() with in turn calls one of the methods on the TableAdapter to send the data to the database. Refer to the tutorial I mentioned earlier for more information about TableAdapters.

Embedded Data Access Code

Another often used solution to the data access code problem is embedded data access code. This means that the business objects fulfill the role of all three layers, and interact with the database directly. While this breaks the layered design principle because the Business Layer and the Data Access Layer are no longer separate, it's still an interesting option as it makes your classes easier to develop and maintain. The biggest problem with this solution is that it often ties your code to a single database, which is one of the main problems that layered design is supposed to solve. To minimize the impact of this design solution, you can use the ADO.NET 2.0 Provider Pattern. With the Provider Pattern you can write data access code in a generic fashion. It allows you to write code that can target different kind of databases, like SQL Server, Oracle, Microsoft Access and so on. The idea behind the pattern is that your code is database agnostic and just uses generic interfaces that are available for all .NET data access providers. A simple configuration setting can then determine the actual database that is used.

For a great open source database helper that uses the Provider Pattern to minimize the code you have to write to target different databases, check out the BinaryIntellect's Database Helper for .NET 2.0. For an introduction to the Provider Pattern, check out the article Writing Generic Data Access Code in ASP.NET 2.0 and ADO.NET 2.0 on the MSDN site.

Separate DAL Classes

The final methodology for data access code that I'd like to discuss involves separate DAL classes for each of your business objects. So, the ContactPersonManager class gets a ContactPersonDB counterpart, EmailAddressManager gets an EmailAddressDB class and so on. The DB extension (which stands for Data Base), is arbitrarily chosen, but helps in determining the role of the classes. From their name, you can see these classes interact with the database, just as the *Manager classes in the business layer are used to manage instances of other classes in the system. These new *DB classes get the same methods, like GetItem, Save, Delete and so on. As parameters, the accept types of the business objects, like ContactPerson and EmailAddress or they accept simple .NET bases types like int.

With the classes for the DAL designed, this is how the class diagram for the data access layer looks:

The Class Diagram for the Data Access Layer

Figure 9 - The Class Diagram for the Data Access Layer

In all four classes, the Delete methods return a bool, to indicate success or failure of the operation. The Save method returns an int that holds the ID of the record that was inserted or updated by the method. The data centric methods, GetItem and GetList both return business objects. GetItem returns a single instance (or null), while GetList returns a custom type that inherits from a generics list. You'll see how this works in the second part of this article series.

To clearly separate the business objects, the business logic and data access layers, I have put all of them in separate namespaces: Spaanjaars.ContactManager.BO for the business objects, Spaanjaars.ContactManager.Bll for the business logic layer and Spaanjaars.ContactManager.Dal for the data access code. Both the business logic layer and the data access layer get a reference to the objects in the BO namespace. Additionally, the business layer gets a reference to the data access layer for all data interaction.

Because I put the business objects in a separate namespace, it's easy to give both the BLL and the DAL access to them. Had I instead put them in the business layer directly, I would have ended up with a problematic circular reference: the BLL needs a reference to the DAL to get items in and out of the database, while the DAL needs a reference to the BLL to understand what kind of objects it needs to return. By moving the business objects to a separate layer, I can avoid this problem.

You can see how this works in the following figure:

The Various Layers of the System
Figure 10 - The Three Namespaces and Their Relations

You can see in the diagram that the Business Layer (Bll) has a reference to both the business objects layer (BO) and the data access layer (Dal) while the Dal only has a reference to the business objects. These relations map one on one to using statements in the code. You'll see this in the second installment of this article series, when the code is discussed.

Now, take another look at the diagram that was introduced at the beginning of this article. Now that you know more about the classes in the different layers and the methods they contain, it's easier to add more detail to the six steps in the process.

Overview of the Different Layers in the Contact Person Manager Application
Figure 11 - The Layers in the Contact Person Manager Application
  1. The Presentation layer, for example an ASPX page called ShowContactPerson.aspx, asks the BLL for some object, for example a contact person. It does this by calling ContactPersonManager.GetItem() and passing it the ID of the contact person.
  2. The BLL can optionally perform some validation and then forwards the request to the DAL by calling ContactManagerDB.GetItem().
  3. The DAL connects to the database and asks it for a specific record. It does this by executing a stored procedure, like sprocContactPersonSelectSingleItem and passing it the ID of the contact person.
  4. When the record is found, it is returned from the database to the DAL in a SqlDataReader object.
  5. The DAL wraps the database data in a custom ContactPerson object from the BO namespace and returns it to the BLL.
  6. Finally, the BLL returns the ContactPerson object to the Presentation layer, where it could be displayed on a web page for example.

You'll see the implementation of these steps in the next part of this article series.

Database Design

It should come as no surprise that the actual database diagram has a lot of similarities with the class design. It has a table for each of the four relevant classes, and each table has columns that map to the properties of those classes. The following image shows the full diagram for the application's database:

The Database Diagram for the Contact Manager Application

Figure 12 - The Database Diagram for the Contact Person Manager Application

In part two of this article series I'll take a deeper look at some of the stored procedures in the database that are used to get data in and out of the database.

This concludes the design of the business and data access layers of the Contact Person Manager Application.

Wrapping it Up

This article covered a lot of ground and made a great foundation for the actual implementation of the code that you'll see in part two of this article series.

The article started off with a short introduction of the sample Contact Person Manager application that is used throughout this article series. This introduction was followed by a discussion of a few design patterns that are available: spaghetti code, SqlDataSource controls, TableAdapters and Linq. The fifth alternative, custom business objects is the main topic of this and the remainder of the articles.

You saw how to turn information gathered in the requirements phase into a number of classes in the object model. These classes and their properties and methods form the API that is used to build the actual Contact Person Manager application.

A large part of the article was dedicated to the actual classes in the system, spread out over three layers: the Business Objects, the Business Logic and the Data Access layer. You saw what classes live in what namespace and what their activities and responsibilities are.

Finally, I have given you a quick look at the application's database model.

Part two of this series shows you how to build the actual classes. You'll see how the database with its tables and stored procedures is created, how to implement the various methods in the business and data access layers, and how to make the contact data (EmailAddress, Address and PhoneNumber) play together with the ContactPerson class so the contact data is available through the ContactPerson objects instead of calling methods in those classes directly.

Download Files


Where to Next?

Wonder where to go next? You can read existing comments below or you can post a comment yourself on this article .


Consider making a donation
Please consider making a donation using PayPal. Your donation helps me to pay the bills so I can keep running Imar.Spaanjaars.Com, providing fresh content as often as possible.



Feedback by Other Visitors of Imar.Spaanjaars.Com

On Monday, February 05, 2007 12:09:51 AM Tahir said:
A useful article indeed. There is one question I would like to ask though. You mentioned that DAL will get parameters rather than objects in order to de-couple the business object from *DB object. However, why would you want to de-couple them anyway because none of them can work without the other. If you want to create this so that you can reuse same classes then it makes sense of course.

Secondly, more importantly, you have Business Objects with Properties + Methods and then *DB objects with Methods. What if in our design we have Business Entities (rather than objects i.e. they only have Properties) and then *DB objects with Methods that manipulate (Retrieve, Insert, Update, Delete) the this Business Entity. E.g. ContactPersonEntity and ContactPersonDB, AddressEntity and AddressDB etc. This becomes more of a Service Oriented rather than Object Oriented. What is your take on this sort of design? What are the pros and cons of the approach I mentioned.

Many thanks

Tahir
On Monday, February 05, 2007 9:35:55 PM Imar Spaanjaars said:
Hi Tahir,

Regarding your first issue: good question! I guess it depends on how you implement other classes, and whether or not you want to reuse the DAL with other BLL layers. While you could reuse the DAL in this example, I wonder if that will ever happen in a scenario like this.

One of the "next steps" in the DAL process would be to create generic data access classes. There are a lot of similarities between al the *DB classes, making for some generic code. I think the CSLA framework by Rockford Lhotka shows off the power of generics in BLL and DAL layers (although he actually merged both layers into single classes), which results in powerful, yet easy to code and understand classes.

Regarding your second point: that's what I meant with dumb and smart classes. I opted for Smart classes because they're easier in ASP.NET 2 data binding scenarios. Also, because all data is contained in a single class, and that class knows everything about itself, it's easier to implement lazy loading. For example, I could postpone getting the contact data for the ContactPerson until the properties were actually accessed.

But, as I said in the introduction, this is just my take at n-tier design. It's not the only way, and I am sure it's not necessarily the best solution. Designing a good architecture is like a search for the holy grail. There are always other ideas to think about, new ways to implement similar behaviors, a constant search for a better design.

Yet at the same time, one of the goals for this article was to explain an architecture that can be understood by many. In more extended frameworks and complex designs, I'd probably use a lot more generics, interfaces and other design patterns. However, in many day-to-day web sites, things don't have to be so complex. IMO, the design from this article should give you the benefits of good design, while still having lowered complexity and ease of implementation.

I am constantly looking for fresh ideas, so I am looking forward to your, and other's ideas on this.

Cheers,

Imar
On Monday, February 05, 2007 9:55:16 PM Tahir said:
Imar,

I appreciate that this article is for general introduction of this subject and its a very good start. The best thing is that you have clearly mentioned the pros and cons of other approaches as well that justifies your solution. I wonder sometimes that why so many books are being written giving examples of e.g. SQLDataSource which is fine for demo/trial releases or extremely small projects, and not detailing the practices used by professionals.

With regards to my query, one opinion I wanted from you is about Service Oriented Architecture. Your design is more of an OOA rather than SOA. What are pros and cons of these two approaches?

Tahir
On Monday, February 05, 2007 10:15:02 PM Imar Spaanjaars said:
They both have their places. In this application, I opted for a more OOA approach. The application asks for it, as it's a data centric application (Obviously, for this article, I wanted to show an OOA approach, and made up the accompanying application).

Bottom line is: things work best in the environment where they belong. A SOA approach doesn't make sense in this application, while the design from this article doesn't make sense in software for a nuclear reactor... ;-)

Imar
On Monday, February 05, 2007 10:19:51 PM Tahir said:
Imar,

What I meant is to ask you your take on SOA and OOA. You mentioned that you used OOA as this is a data centric application. What are applicaion paradigms for these two architectures. In other words what applications are best suited to SOA and what type of applications for OOA.

Many thanks

Tahir
On Tuesday, February 06, 2007 10:09:00 AM Tahir said:
Imar,

I have seen the BuBase application you wrote for your wrox book. That is more of a SOA (I think) where there is an entity Bug, a business service BugManager and a data access service BugManagerDB.

Would you consider this as SOA? I think BugBase architecture is more flexible, how would you compare that architecture with the one you presented in this article?

I am just trying to get a feel how I can use your ideas(architectural) in one of the projects that I am working on now a days. Its a bit more larger in scale then the one your presenting in this article but of course this article is then a good starting point for discussions like these and I would hope that you dont get fedup from my questions :)

Many thanks

Tahir
On Tuesday, February 13, 2007 12:34:04 AM Tahir said:
So far so good :). I think this is much better than the previous arrrangment. This design is flexible and clean. I am now waiting for the part 2.

Tahir
On Wednesday, February 14, 2007 11:05:25 AM Alex said:
Good!!! I am waiting part 2.

Could you talk about transaction between data objects, please ?

On Wednesday, February 14, 2007 1:52:48 PM Simon said:
This is an excellent article, very well written with a clear explanation of all of the different approaches. Do you have any idea when you will publish the second part? (Not trying to rush you - just very interested in your approach)

On Wednesday, February 14, 2007 1:58:27 PM Imar Spaanjaars said:
Hi Alex,

What exactly do you mean with "transaction between data objects"? The idea I have in mind is that ContactPerson is responsible for setting up a transaction that spans updates for Address, EmailAddress and PhoneNumber as well.

Is that's what you mean? If so, you'll get what you're looking for in part 2.

Cheers,

Imar
On Wednesday, February 14, 2007 2:25:39 PM Imar Spaanjaars said:
Hi Simon,

Hopefully I'll be able to publish part 2 this weekend, somewhere on or before February 18....

Imar
On Wednesday, February 14, 2007 2:47:02 PM Alex said:
Yes, I meant "transaction spans business entities" (ex. Order and OrderDetails).

Now, I am waiting for the part 2.

Thanks, Alex.


On Thursday, February 15, 2007 5:33:50 PM Tahir said:
Imar,

Alex mentioned about transactions which is a good point. Can I also add that it will be very useful to see how errors/events can be handled in the application in a more structured way. It would be nice of you to have something about this as well. I consider this an important aspect of N-Tier design. If you think otherwise then dont bother with it :).

Tahir
On Thursday, February 15, 2007 5:43:38 PM Imar Spaanjaars said:
Hi Tahir,

Although I agree with you, I am not going to cover that. I am already having problems keeping the article under 50 pages.... ;-)

Imar
On Thursday, February 15, 2007 5:49:00 PM Tahir said:
Hi Imar,

:) Yeah your right I guess. Well looking forward to read subsequent parts...

When do you think these will be available though?

You must be fedup of me for pesting you with so many queries ;). I am afriad you will have to live with it or else ask me explicitly not to bother you Ahh I know that you wont do :)

Tahir
On Wednesday, February 28, 2007 1:11:24 AM Wayne said:
Really good article Imar. I'm glad you have taken the time to explain N-Tier architecture for beginners like myself.  I recently purchased your book ASP.NET 2.0 Instant Results and I couldn't have been more satisfied with a book.  I hope you keep writing good articles like this one very informative.

What is the difference between entity classes and domain object classes?


On Wednesday, February 28, 2007 7:48:17 AM Imar Spaanjaars said:
Hi Wayne,

One difference is that the former has  98,300 results on Google while the latter only has 1240 ;-)

But seriously, I think it's just a matter of terminology. I don't use the term "domain object classes" but AFAIK, it is used, just like the term "entity classes" to refer to classes in your bussiness domain.

Imar
On Wednesday, March 07, 2007 12:14:42 PM PohEe.com said:
Your article is awesome. This is the best article i ever seen on describing Multi-layered design in ASP.NET. I love it so much.
On Wednesday, March 07, 2007 2:28:09 PM Nirvana said:
Good Article
On Wednesday, March 07, 2007 4:34:52 PM Richard Marriott said:
A nice, well written, article. You see so many explanations of this topic done in a bad way that it could be very off-putting to the person trying to learn from it. This article certainly does not fall into this category.

One opinion of mine though (again, taking into account that it is probably just another way of doing it). Would it not be cleaner (from a logistics point of view) to replace the *Manager classes with static methods on the actual business classes? The main reason would be that in larger projects having the amount of classes halved (i.e. by not having the *Manager classes) would be a large advantage if 50+ business classes are required. (Although I do appreciate that your approach was aimed at a small-medium project).

Moving the methods from the *Manager classes to be static methods on each business class would also not invalidate your dumb class approach as these methods would not be changing the state of any particular instance of a business class.

Well done again,
Rich
On Wednesday, March 07, 2007 5:00:18 PM Richard Marriott said:
Sorry about the formatting in the previous post, don't know where my line breaks got to!
On Wednesday, March 07, 2007 5:36:12 PM Imar Spaanjaars said:
Hi PohEe.com and Nirvana,

Thank you! Spread the word, spread the word!! ;-)

Imar
On Wednesday, March 07, 2007 5:44:49 PM Imar Spaanjaars said:
Hi Richard,

I see your point, but it would either introduce the issue with circular references I talked about, or give you a very messy DAL API. I considered your ideas in a beta versio of this articles series but decided against it for the following reasons.

If the Business Logic and the Business Object layers are merged (which, I believe, is what you're proposing) your DAL needs a reference to your BO/BLL layer so it understands how an Address looks like. At the same time, the BO/BLL layer needs a reference to the DAL so it knows how to call methods like Save to save the items.
You could solve that by using interfaces: your have a separate layer that defines the looks of a class with an interface. Then the BO/BLL and DAL both use types of these interfaces to work with.
However, I think at the end you end up with the same amount of code and files.

As an alternative, you can merge the BO/BLL layers and give the DAL methods with only simple .NET types. E.g.:

SaveAddress(string street, string houseNumber, string zipCode, string city)

However, that can *quickly* become very messy.

So, in all in all, I think my current solution is the best mix between the layers, the amount of files and code, and cleanliness of the API.

Looking forward to further ideas you may have on this.

Cheers,

Imar
On Wednesday, March 07, 2007 9:55:16 PM Mike said:
Great article man! You are like the consultant we don't have. I'm looking forward to actual implementation.

Is the DAL coupled to one type of database, like SQL Server, so you would need to completely re-implement it to support Oracle?
On Wednesday, March 07, 2007 10:33:48 PM Imar Spaanjaars said:
Hi Mike,

You can always try to hire me.... ;-) (www.designit.nl)

Regarding implementation: did you read parts two and three of this article series? They show you how to build the various layers and how to use them in a web site.

In my case, the code is written for SQL Server, so yes, you'll need to rewrite it if you want to target Oracle. However, you'll find that there's isn't that much code that needs to be changed; most of the code in the DAL can be reused as is, and obviously, you don't need to touch the BO and Bll layers at all.

And, if you're using the BinaryIntellect's Database Helper for .NET 2.0 I talked about in this article, you have to rewrite even less code. Of course, there'll always be differences in how the database is used (for example, whether you can use stored procedures or not) so you still need to write different code for different databases, but you can really minimize the differences, making it easier to switch.

Hope this answers your question.

Cheers,

Imar
On Thursday, March 08, 2007 9:40:19 AM Goran said:
Hello again Imar!

Great article!

Be patient with my english, I really suck in this language(at least writing it).

But I would have combined "the three address classes" (Phone, Email and Address) into to one class.  And have a AddressType containing Phone, Email and PostalAddress.

The same for the collections/list classes, one AddressList.

And the same for management classes. Only one AddressManager.

Finally the same in the database, only one Address table,
and a Type table containing Phone, Email, PostalAddress  

Why this way, because I always make the database design before the object model design. I always found it easier to make relational database design than designing an object model.

How about that?

/Goran
On Thursday, March 08, 2007 1:16:54 PM Gav said:
Hi Imar,

Just a quick note to re-itterate what everyone else has already said - great job with this article. Much better than any white-paper you might find on MSDN!
On Thursday, March 08, 2007 8:21:47 PM Imar Spaanjaars said:
Hi Goran,

I am not sure I understand what it is you have in mind. Or, if I do understand, I am not sure I agree.

Why would you want to make all classes look the same? Because it's easier to code? I don't think that counts as a good reason. Are you proposing to give your class properties like EmailText, PhoneNumber, Street and ZipCode at the same time?

That would make it really hard to use the object.

Also, by separating things out to separate classes, you can build an intuitive object model. For example, on the Addresses list you can create a property of type Address called PostalAddress. This property would loop through the list to find an Address with its type set to Postal. Then an end-developer could call this:

Address myAddress = Addresses.PostallAddress;

If you start mixing stuff you get very weird behavior. In the example above, the myAddress object would contain an (empty) EmailText property. Pretty weird for a PostalAddress.

The same applies to your database design. Why would you want to store all (seemingly related) data in a single table? You might as well store the ContactPerson in that table as well, and call it Object.... ;-)

Maybe I am missing something in what you're proposing here, but I don't think your ideas will lead to a design that's easy to use by others....

Imar
On Friday, March 09, 2007 6:24:55 PM Terry said:
Great article.

Looking at your diagram showing references between the *layers*.  Did you do that in the standard class designer in VS2K5 Professional?
On Friday, March 09, 2007 7:25:46 PM Imar Spaanjaars said:
Hi Terry,

I indeed used Visual Studio's class designer to get the general look of the diagram and then used Photoshop to remove the elements (class for example) I didn't want on the diagram.

Imar
On Sunday, March 11, 2007 3:35:51 AM Paraag P Kantharia said:
In future with C# 3.0 ( Orcas Time Frame ) the coding for business objects is going to be more simpler than today.

So its better to stick to Imars Suggestion of Business Objects from Day one and be ready to save more lines in future.

I am writing a simple code ( C# 3.0 ) based on Imars Code ( C# 2.0 ) above


public class ContactPerson {
        public string FirstName { get; set; }
        public string LastName  { get; set; }        
        public int    Age       { get; set; }
    }

Thanks Imar, very good going. I really like the style an the way you explain the codes. It even makes tougher things easier.

Paraag P Kantharia
On Monday, March 12, 2007 6:20:02 AM Dastagiri said:
This article is good and helps to improve the readability and clean coding and it will reduce repetetion also.
On Monday, March 12, 2007 10:40:42 AM Boris Yeltsin said:
I use LLBLGen and it gives me all of the above capability with very little work. It generates all the classes for me and I can just extend them as they are partial classes, where needed.
On Thursday, March 15, 2007 9:36:18 AM beyondjay said:
I think *Manager class is not necessory. As a class, it should manager some data by itself. These method could be added in corresponding objects.
what do you think?
On Thursday, March 15, 2007 9:58:47 AM Imar Spaanjaars said:
Hi beyondjay,

What I think is what I wrote in this article. I discussed the differences between "dumb" and "smart" classes earlier in the article....

Imar
On Thursday, March 15, 2007 1:53:04 PM Maran said:
Execllent Article for beginners who wants to follow the 3-tier architecture design, Keep up the good work.
On Thursday, March 15, 2007 11:23:38 PM dan silk said:
How do you implement GridView sorting in gvContactPersons?

Thank you
On Thursday, March 15, 2007 11:27:03 PM Imar Spaanjaars said:
Hi dan,

Check out my comments of 3/13/2007 on part three of this article series.

Cheers,

Imar
On Friday, March 16, 2007 1:37:23 PM Jozef Ševcík said:
Pretty nice article, great job.
On Wednesday, March 21, 2007 11:11:26 AM Bassem Gomaa Mohamed said:
suppose we want to add a contact to our data base and we should check if the contact name already exists or not . the check result  should be displayed to the user how can that is done using the sql data source.
On Wednesday, March 21, 2007 8:24:20 PM Imar Spaanjaars said:
Hi Bassem,

Here's what you should do:

1. Modify the sproc that inserts the CP so it uses IF EXISTS first to see of the CP exists. If it does, return a special return value.

2. If the CP exists, have Save return some value, like a custom Enum (SaveOperation.RecordExists for example)

3. Handle the Inserted event of the ObjectDataSource and retrieve the ReturnValue, like this:

YourType theValue = (YourType) e.ReturnValue;

Based on the value of theValue, update the UI.

Hope this helps,

Imar
On Monday, March 26, 2007 6:48:55 PM Mark Henke said:
Imar, I question whether the DAL should reference the Business Objects at all? Should this Alyer even know anything about the Application or It's Business Classes/Ojects at all in a true Tiered Application.

Should the DAL not return Generic Objects and / or List to be Cast into the Business Object Types by the respective Manager Classes?

Is this even possible or am I just relating another variation. I would like to use th MS Enterprice Data Application Block to return the Data in the form of a IDataReader object to Populate the Objects in the BLL. Or should I just return a generic list or OBJ right away? Is this a viable approach?
On Monday, March 26, 2007 7:27:52 PM Imar Spaanjaars said:
Hi Mark,

There are a few ways to get data out of the DAL, like custom objects (by returning BO objects like in my example, or by Interface types) or through data related objects like DataSet, *DataReader etc.

Even if your DAL would return "generic objects", these objects would still be business objects. That is, you could return them as Objects, but they would still be ContactPerson, Address and so on if you want to be able to cast them to those types. Since that doesn't add much, IMO, it's not bad to have the DAL refer to the BO layer. After all, it's the DAL that saves these kind of objects. To be able to save it, it has to understand its properties, types etc.

To further abstract data access logic away from the DAL, you can use layers like the DatabaseHelper class I talked about earlier.

Hope this clarifies things.

Imar
On Wednesday, March 28, 2007 7:33:58 AM navdeep said:
This is surely a masterpiece.

I am new to designing. So please bear with my queries:)

"I could postpone getting the contact data for the ContactPerson until the properties were actually accessed."

this is a quote from your comment to Tahir. Please throw some light on this.

Secondly, can you please help me out ( rather guide me ) by refer few weblinks or books to get started to designing ( arch ).

Many thanks,
Navdeep
On Wednesday, March 28, 2007 6:25:45 PM Imar Spaanjaars said:
Hi navdeep,

The original comment was based on a previous version of the article, where I used smart classes instead of dumb classes. Eventually, I changed the design so the comment doesn't really apply anymore. However, if you were using smart classes, you could implement lazy loading like this:

public  AddressList  Addresses
{
    get
    {
      if  (addresses  ==  null)
      {
        addresses  =  Address.GetList(this.id);
      }
      return  addresses;
    }
    set
    {
        addresses  =  value;
    }
  }

This (currently not compiling) code postpones getting data by calling GetList() until the very first time the data is requested. If no-one ever calls the get accessor for the Addresses property, than GetList isn't called either.

Hope this helps,

Imar
On Thursday, March 29, 2007 1:50:33 AM Navdeep said:
Thanks Imar for the prompt response.

Can you refer me some tips/your articles or some weblinks to learn designing of .net applications.

Thanks,
Navdeep
On Thursday, March 29, 2007 5:35:19 AM Imar Spaanjaars said:
Hi Navdeep,

I don't have any concrete tips or links for you. But in general, look at sites like www.asp.net, Microsoft's MSDN site and the major ASP.NET site like 4Guys.

Also, try Googling for a few keywords you're interested in. Then read the blogs that people write about the topic, and follow links to other sites and articles.

Imar
On Friday, March 30, 2007 4:13:03 AM Frank said:
Hi Imar

I have learn not to use stored procedures, not that they are bad, but they ties you to the database.
Is this something that i have misunderstod, or just your way of doing things?

Would it be better to use things like nhibernate?
Could you come up with some pros and cons?

Thanks
Frank
On Friday, March 30, 2007 6:06:03 AM Imar Spaanjaars said:
Hi Frank,

In this case it doesn't matter much as the whole DAL is tied to SQL Server.

If you use the DatabaseHelper I talk about in one of the articles, you can minimize the differences between database vendors. However, stored can indeed be problematic as not all database vendors understand them, or use them in the same way.

So, you may want to stay away from them if database independence is important. Using technologies like NHibernate may also help in this.

Imar
On Friday, March 30, 2007 7:51:57 PM Krishna said:
Excellent, really great work.
On Saturday, March 31, 2007 12:35:36 PM ali said:
hi
thanks for your excelent article
I have question.do you suggest any reference about 3-tier applications on asp.net2.0?

Thanks
ali
On Saturday, March 31, 2007 12:46:49 PM Imar Spaanjaars said:
Hi ali,

Please read my reply to Navdeep.

Imar
On Sunday, April 01, 2007 9:24:15 PM Przemek said:
I have a class that represents a picture. This class will have multiple attributes that will describe it: eyeColor, hairColor etc.

Questions: should I use enumerators to hold these values: eyeColorType enum will have (black, blue, green...etc) and so on for all the other attributes.

If that is the case what names should I give to these enums in my class. In your example each of your classes has only one "type", but mine will have multiple ones.

Thank you.
On Sunday, April 01, 2007 9:29:21 PM Imar Spaanjaars said:
Hi Przemek,

I would use the Color struct for that. It contains convenient members representing known color names, but also has methods to convert from other types of info to a Color. E.g.:

Color myColor = Color.LawnGreen;
Color myColor = Color.FromName("Red");

Not sure what you mean with "each of your classes has only one "type", but mine will have multiple ones."

Cheers,

Imar
On Sunday, April 01, 2007 9:47:53 PM Przemek said:
What I meant was that ContactPerson class had only one Type for it's property.
I'm assuming that the type property refers to the ContactType enum. So a contact person can be personal or business.
In my case each of my pictures will have multiple types, so one picture can be described using multiple types: blue eyes, long hair etc.
Does that make sense. I am completely new to designing things this way in Visual Studio so I maybe approaching this completely the wrong way and that is why it doesn't make sense to you.
On Monday, April 02, 2007 6:17:48 PM Imar Spaanjaars said:
Hi Przemek,

It depends on how you want to look at your data. In my case, a single Type property is enough to determine what kind of Address I'm dealing with.

Obviously, you extend that to whatever you like. You can reuse the same Enum (or similar types) for multiple properties. For example, the Color struct would be a good example of that. You can easily have multiple properties of type Color, like HairColor and EyeColor.

Hope this helps,

Imar
On Monday, April 02, 2007 6:41:41 PM Przemek said:
So I've done some reading up on Struts in C# and I think I will stick with the enum way of doing things: reason being that I will have about 100 enums and each of those will have like 15-20 properties. From what I understand using a struct for such large data is not recommended.

One more question has come to mind while I was reading. From what I understand the "Type" values are stored in enum (code), in your example. Could you not have stored them in a code table in a database or does this break the layering of the application? Or is it a performance issue becuase reading from a DB is slower then reading from memory?

Thank you.
On Monday, April 02, 2007 7:03:27 PM Imar Spaanjaars said:
Hi Przemek,

That often depends on the number of items in the list and whether they are likely to change or not. For example, I would never store a list of countries or cities in an Enum, but would use a look up table instead.
However, for simpler types like Gender, or ContactType you can store them in an enum as well.

Imar
On Monday, April 09, 2007 3:16:42 PM Qingxiong said:
Hi, Imar. I am impressed with your article. You did a great job.
If you can provide both VB and C# version, it will benefit more readers.
On Monday, April 09, 2007 7:58:07 PM Imar Spaanjaars said:
Hi Qingxiong,

Glad you like the articles.

I considered a VB version. However, considering the amount of work it took to create the C# version of both the articles and the application, I decided not to do it. IMO, the main focus of these articles is the concepts behind it; not necessarily the code it takes to create the actual application.

However, if someone wants to translate it to VB: I'll be happy to host the download on my site.... ;-)

Imar
On Tuesday, April 10, 2007 11:42:40 AM SIVAKUMAR said:
Nice Topic , I have included the reference of the Farpoint sheet in the asp.net project. It is available in the Toolbox and But not enabled in the toolbox , how to make this spreadsheet control(thirdparty control) in the tool box control of the asp.net application
On Tuesday, April 10, 2007 12:22:37 PM Imar Spaanjaars said:
Hi SIVAKUMAR,

Farpoint sheet?? I have no idea what you're talking about. I also don't see how this is related to the original topic of this article.

If it's a third party product: I suggest you consult their website.

Cheers,
Imar
On Thursday, April 19, 2007 4:49:14 PM Emeka said:
Hi Imar,

Thanks alot 4 this article, it's the best i've seen on the N-tier architecture. Was wondering if you had writen any articles on design patterns.

Thanks agin 4 the article.
On Thursday, April 19, 2007 8:16:45 PM Imar Spaanjaars said:
Hi Emeka,

Glad you like the article.

I wrote a book called ASP.NET 2.0 Instant Results that features a few design patterns similar to the one described in these articles. The book comes with 12 fully working applications and an explanation of their architecture and code. For more details, check out this page on my site:

http://imar.spaanjaars.com/AboutMyBooks.aspx?aboutitem=instantresults

Cheers,

Imar
On Tuesday, April 24, 2007 11:00:09 PM csharpdev said:
I don't understand what problems result from what you refer to as a "circular reference" when you are talking about separating the business objects from the business logic. As long as you make sure you have static (in VB, shared) methods that return instance objects and instance object collections, I don't see the problem. Also it seems more in line with OO design to encapsulate properties and methods together for each object type you are modeling. Are you using these "dumb" business objects because that makes for a easier to understand tutorial or because in you're experience it makes for a more flexible application? Thanks!
On Wednesday, April 25, 2007 6:19:45 AM Imar Spaanjaars said:
Hi csharpdev,

Check out my comment from3/25/2007 on the second part of this article for my take on circular references: http://imar.spaanjaars.com/QuickDocId.aspx?quickdoc=419
Generally, it'll work, but there are circumstances where it won't or cause problems.

I am using separate BOs in the real world as well; in fact, I tried to make this article "as real world" as possible, so it's easy to implement after reading it. Many articles give you a very abstract overview, leaving the actual implementation to you.

But, I also sometimes use "smart objects" in some projects.

Imar
On Wednesday, April 25, 2007 8:01:28 PM Rob said:
Thank you first of all for the Article.....

Would you be able to show me/us how to use the PUBLIC "Validate" method?

I believe I am supposed to declare it in the emailAddressManager class and use it in a .aspx.cs

thank you.
On Wednesday, April 25, 2007 8:11:34 PM Imar Spaanjaars said:
Hi Rob,

Check out part 2 of this article series; it shows how to write and call a Validate method.

Cheers,

Imar
On Friday, May 04, 2007 10:28:25 AM Anwer said:
In this architecture Object is returned after getting qurey result, and this object may contain a particualr type like, Address, ContactPerson and so on. What if I use joining table like "Select Contact Name , Address where....." Here You can see Conact name is from different class and Address is from different Class. How would you map this recordset containing two classes entities, while in this architecture we have only separate classes not composite classes.

Best regards
On Friday, May 04, 2007 10:43:08 AM Imar Spaanjaars said:
Hi Anwer,

Please don't post the same message more than once on different articles.

It all depends on your design and your queries; you could use the result set to build up a ContactPerson and at the same time instantiate and fill a new Address object which you assign to the Person.

Imar
On Wednesday, May 09, 2007 3:16:23 PM Grant said:
Imar,

I was just going back over this article and I am curious, why did you choose to use enums instead of database tables to store contact type and person type?

If you were to run it out of database tables instead of using enums would you then just need to bind that dropdown box to the appropriate database table?

On Wednesday, May 09, 2007 3:18:28 PM Grant said:
Oops,for got to ask, if so, how would you bind the dropdown to the database table?
On Wednesday, May 09, 2007 5:05:47 PM Imar Spaanjaars said:
Hi Grant,

Check out the question from Przemek on Monday 4/2/2007 8:41:41 PM in this comment list as he has the same question.

If you want to get it from the DB, create a simple class like NameValue with a Name and a Value (or a Key and a Value). Then follow the same principles from this article and bind the drop-down to the GetList method.

Cheers,

Imar

On Wednesday, May 09, 2007 6:16:49 PM Grant said:
Imar,

I'm not sure I'm understanding what you're telling me to do. Can you direct me to an example?
On Wednesday, May 09, 2007 6:25:41 PM Imar Spaanjaars said:
Hi Grant,

This entire article series is the best example... ;-)

Instead of creating a class like Person, create one called NameValue. Give it two properties: an int for the key / ID and a string for the Value. Then implement the other methods as per this article. E.g. create a GetList method that returns a list of NameValue objects. In this method, execute a stored procedure that does something like SELECT Id, Description FROM PersonType ORDER BY Description.

Then you can use the results from GetList exactly as you saw with the other stuff in this article: create an ODS that executes the GetList method. And then use a drop down list to get the data from the ODS.

Does this help?

Imar
On Wednesday, May 09, 2007 6:38:28 PM Grant said:
Oh, so I'd just create set of classes for it then like we did for COntactPerson (e.g. NameValueList, NameValueDB, etc...)  and then bind the dropdown to the GetList method in the Manager class. Cool. For some reason I thought it would be harder than that.
On Wednesday, May 09, 2007 6:44:13 PM Imar Spaanjaars said:
Yeah, exactly.

Then you can store the Id of the NameValue in the PersonType property of the ContactPerson.

Cheers,

Imar
On Wednesday, May 09, 2007 6:46:28 PM Grant said:
Dude you just so rock! If you're ever in my neck of the woods Dinner and Drinks are on me.
On Saturday, May 12, 2007 8:12:48 AM Imar Spaanjaars said:
Haha, thanks; I'll keep that in mind.

Imar
On Saturday, May 12, 2007 12:36:04 PM Grant said:
Okay I made the  classes for NamValueListDB etc now I am getting Cannot implicitly convert type int to PersonType errors. How should I resolve them?
On Saturday, May 12, 2007 12:52:32 PM Imar Spaanjaars said:
Hi Grant,

The Type of a Person is now no longer a PersonType as you're not using an Enumeration anymore. You'll now need to define the Type as a simple int.

Cheers,

Imar
On Thursday, May 24, 2007 3:32:58 PM EC said:
Imar,

Great article, also have your instant results book.  Quick question is have you evaluated Subsonic DAL code generator developed by Rob Connery and if so what are your thoughts.  Apologize in advance if you have already commented on the subject.

Thanks, EC
On Saturday, May 26, 2007 11:12:51 AM Imar Spaanjaars said:
Hi EC,

I experimented with it a few times, but haven't used it much in real-world projects (yet).

Cheers,

Imar
On Tuesday, June 05, 2007 6:25:42 PM Richard Lelle said:
Imar,

Great article!  It really has helped me a lot.  I am looking forward to parts 2 and 3.

Question/concern:  I used the 'class diagram' tool to define all my classes.  It worked beautifully.  When I was finished, I went to put namespaces in my BO classes to tie them together.  When I would add a namespace, the graphic depiction of that class would disappear from the class diagram.  If I remove the namespace reference, the image re-appears.  Any ideas as to why this would happen?

Thanks!
On Tuesday, June 05, 2007 7:03:04 PM Imar Spaanjaars said:
Hi Richard,

In case you hadn't noticed: part 2 and 3 are already available.

When you change the namespace of a class, you effectively change the type of that class. The reference to the "old" class is no longer valid, so it's removed from the diagram. Simply drag it from the Solution Explorer and drop it on the diagram again to add it back in.

I don't know why the Class Designer is not able to track these changes and update the diagram automatically.

Cheers,

Imar
On Friday, June 22, 2007 8:34:57 AM Adnan said:
Brilliant article Imar.

You've managed to explain the logic and power behind N-Tier apps where so many other sites failed.

Very impressed with your reasoning for the different methods and solutions,  looking forward to similar articles and I've just ordered your book.

Thanks
On Tuesday, July 10, 2007 11:13:43 AM Nick Nelson said:
Imar,

First we all owe you for this great set of articles. Well thought out and even better plainly explained.

The logic in combining the Insert and Update methods into a single Save method in the DAL is clear. But I wonder if it wouldn't be better to keep them separate in the BLL. Aren't inserts and updates logically different operations in a business sense?

An example very common in the real world is in a system where there is legacy data from an old system where the validation rules may well have been different. While you will want all new transactions to adhere strictly to the new validation rules, you don’t necessarily want updates thrown out because they adhere to the old validation in some way that is not relevant to the amend the user is making now.

Also there may well be different validation rules concerning those users who are permitted to do inserts and updates.

Splitting the combined BLL method into insert and update methods (both calling the save method in the DAL) is easy following the techniques in your articles which reinforces the strength and flexibility of your design. Well done!

Nick
On Tuesday, July 10, 2007 11:31:06 AM Imar Spaanjaars said:
Hi Nick,

I completely agree. For the scenario you describe it would be logical to split the Insert and Update methods.

Cheers,

Imar
On Tuesday, July 10, 2007 11:40:19 AM Muhammad Zeeshanuddin Khan said:
Hi

Imar I want to ask you that the namespace order which you prefer. I think there is much better way to do it.

You Add the Namespace Dal then also add Db with the class name
same with Bll.

If you are making the separte namespaced then is there any need to add postfix to class name

Regards

Muhammad Zeeshanuddin Khan
On Tuesday, July 10, 2007 12:09:43 PM Imar Spaanjaars said:
Hi Muhammad,

Sorry, I don't understand what you're asking.....

Imar
On Wednesday, July 11, 2007 4:07:34 AM Muhammad Zeeshanuddin Khan said:
Imar I want to ask you that

You put AddressManager Class
in namespace Spaanjaars.ContactManager.Bll

Why don't you Named that class Address
Because you put this in Bll

I am working on a project and confuesd to make the namespace structure
I selected to create the structure like CompanyName.ServiceName.Bll

Do you agree with that or do you have any better idea?

Waiting for your reply.

Regards

Muhammad Zeeshanuddin Khan
On Wednesday, July 11, 2007 5:34:41 AM Imar Spaanjaars said:
Hi Muhammad,

ContactManager (or Contact Manager) is the name for the entire application. It's at the same level as Microsoft.Word.UI for example where Word is the name of the application. It's common to name smaller projects something CompanyName.ProductName.Layer.

Imar
On Wednesday, July 11, 2007 7:06:47 AM Muhammad Zeeshanuddin Khan said:
Hi Imar

I think I did not convey you my question.

I am asking.

You worked on BO, BLL, DAL
And choose the class name Address, AddressManager, AddressDB
in the respective manner.

I am asking
if you named three classes the same Address and put them in the respective namespace like BO, BLL, DAL
Then I think it would better.

Did you get?

Regards

Muhammad Zeeshanuddin Khan
On Wednesday, July 11, 2007 7:59:07 AM Imar Spaanjaars said:
Hi Muhammad,

You can do that too; it doesn't really matter and it all comes down to personal preference.

I prefer to have something like *Manager and *DB to indicate the purpose of the class. Even though they are in separate namespaces, it's easier if they have a clear name. But of course you can choose whatever you want. You could call all of them A and it would still work.... ;-)

Cheers,

Imar
On Wednesday, July 11, 2007 8:54:31 AM Muhammad Zeeshanuddin Khan said:
Hi Imar

Can I ask you that you choose the Database table names in Singular.
As recommendations are in Plural.
Like you choose ContactPerson and recommended is ContactPersons.

Can you tell me that why don't you apply the recommended rules.

Regards

Muhammad Zeeshanuddin Khan
On Wednesday, July 11, 2007 9:11:16 AM Imar Spaanjaars said:
Hi Muhammad,

Tell me what recommendations you are talking about. I think I have seen just as many recommending singular fiorm as plural form. Personally, I prefer to use singular form as, IMO, it often makes queries a bit more readable.

But again, it's personal preference. This article merely shows you a way to design n-layer web applications. You are free to implement your own naming guidelines and best practices, just as I have done with this article.
If you don't like them, just change them.

Cheers,

Imar
On Wednesday, July 11, 2007 9:55:44 AM Muhammad Zeeshanuddin Khan said:
Hi Imar

Don't feel bad.

Your article is really the best available currently on the web.

And a lot of developers are reading.

That's why I want that everyone should follow the recommendations which are exposed by professionals and not by ourselves.

Related to the Naming Conventions about Tables I read many article but the latest and best one is

http://weblogs.asp.net/jamauss/articles/DatabaseNamingConventions.aspx#Tables

Please read this.

Waiting for your reply.

Regards

Muhammad Zeeshanuddin Khan

On Wednesday, July 11, 2007 11:02:51 AM Imar Spaanjaars said:
Hi Muhammad ,

Naming guidelines are just that: guidelines.
There is often no right or wrong; only things that seem logical or that most people prefer, use or like. Writing things down so at least everyone uses the same convention is obvously a good thing, especially within a company.

Don't get stuck on "hard coding guidelines" or you'll be stuck forever, without the flexibility to change the way you work. In fact, if you're so eager to read and believe the guidelines by Jason Mauss, you should also read his follow-up post and the comments from AndrewSeven and Jason's own comments on that.

http://weblogs.asp.net/jamauss/archive/2004/05/10/129448.aspx

As you can see, also the guys that come up with guidelines can change their minds. Maybe Jason is still recommending singular, maybe not. The point is there are often no hard guidelines.

The internal guidelines my company uses says to use singular form for a number of reasons, so that's what I use as well (I wrote them).

But again, feel free to do whatever you like. Just don't get stuck on hard and fixed guidelines someone else wrote. Learn from others, and then make up your own mind....

Imar
On Wednesday, July 11, 2007 11:17:36 AM Navdeep said:
Hi Imar and Muhammad,

I have been following up your conversation. I do feel the same. Guidelines are there to guide you. We should pick what suits our req the most and make our work easier.

Keep up the good work.

Cheers,
Navdeep
On Wednesday, July 11, 2007 11:40:41 AM Nick Nelson said:
As Navdeep says interesting conversation.

I designed my first relational database (IBM mainframe DB2) about twenty years ago and we were taught to use singular form for table names because the name should represent a logical row instance and not say anything about the collection of rows that may or may not be present in the table.

When looking at other people's systems the conventions used quickly become apparent and in the end the only rule you MUST absolutely follow is to be internally consistent on naming conventions within any given application.

Nick
On Wednesday, July 11, 2007 5:55:29 PM Imar Spaanjaars said:
Hi Nick and Navdeep,

Couldn't agree more; it's important to have guidelines that make sense, but it's even more important to stick to them where applicable.

Where I work we have a set of guidelines that I initially wrote. It's a 30+ page document detailing many things in software development ranging from naming guidelines for database and other objects / variables to project setup and design.

About once a year, the entire development team is asked for input on the current standard and then we hold a discussion session to see what's up to date, what we like and don't like and what we can do to better *support* our development efforts. I don't believe in guidelines that people follow just because they are the guidelines; I do, however, believe in consistency across people's work, making it easier to swap one developer with another for a certain project. IMO, guidelines really help in creating consistent software which is good for everyone.....

Imar
On Thursday, July 12, 2007 4:38:04 AM Navdeep said:
Hi Imar,

Will it be possible to share your thoughts and may be post something on guidelines you just mentioned. It will be great to know about your views on it.

Cheers,
Navdeep
On Thursday, July 12, 2007 5:14:03 AM Muhammad Zeeshanuddin Khan said:
Hi Imar and others

I think I am unable to convey my message to you all.

I am writing these messages to convey my thoughts which may be right or wrong.

But what I learnt from my experinced is that we should follow the standard guidelines. This will help others to understand quickly.

Am I right?

Regards

Muhammad Zeeshanuddin Khan
On Thursday, July 12, 2007 7:19:14 AM Imar Spaanjaars said:
Hi Muhammad,

Well, yes, that's more or less what I said too in my last message.

The difference in opinion may be that you keep referring to "the guidelines" while I prefer to refer to just "guidelines".

IMO, there is no such thing as "the guidelines"; guidelines are not set in stone; they change, evolve, become obsolete and so on. If you're only working with a single set of guidelines and never reevaluate them, you end up becoming a rigid programmer which won't do you any good.

Ask yourself "why exactly am I doing this and that in this and that way"?? If the answer is "Because we have been doing it like this for the past 5 years", it's time for a reevaluation of the way you work and the guidelines that support that work.

Cheers,

Imar
On Thursday, July 12, 2007 7:32:54 AM Imar Spaanjaars said:
Hi Navdeep,

Most of our guidelines are based on other guidelines and then modified to suit the way we work. A good place to start (for .NET) is this book: "Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries" published by Addison-Wesley  and written by two Microsoft employees.

You may also want to take a look here: http://blogs.msdn.com/ericgu/archive/2004/01/19/60315.aspx

It starts by linking the well known iDesign guidelines but comments from users point to more guideline documents.

Cheers,

Imar
On Thursday, July 12, 2007 9:36:32 AM Muhammad Zeeshanuddin Khan said:
Hi Imar

You write that article very very good.

And If you write another one to explain the difference between Layered Model and others. And detail look for Benifits and Disadvantages. Then this will really the another big one.

Because I don't found an article in this regard. If you have then please send the link

Regards

Muhammad Zeeshanuddin Khan
On Thursday, July 12, 2007 9:51:51 AM Nick Nelson said:
Hi Muhammed,

Reiterating what Imar said, nothing you have said is wrong but the fact is there are may different sets of guidelines. There isn't a common set of rules and even different people within Microsoft have different opinions on on the best naming conventions.

You should maybe pick a set of guidlines that make sense to you, use them for this project and then at the end of the project evaluate what you liked about them and what you didn't and then adapt them accordingly for your next project - again as Imar said.

But don't spend more time worrying about what guidlines to follow than you do designing and coding or you'll never get your project delivered to your clients on time, which is after all what we are paid to do.

Good luck with the project.

Nick
On Thursday, July 12, 2007 10:04:44 AM Imar Spaanjaars said:
Hi Muhammad,

I don't think I'll write an article just explaining the differences between the various models. Part 1 of this series mentioned the most popular models and explained the differences between them and the advantages and disadvantages they have.

The rest comes down to experience: try them out and see what you like best. Just as with the guidelines, there are things you may like better than others. There is no silver bullet Someone at DotNetKicks put it like this:

(http://tinyurl.com/3eyfj6)

"I would much rather be able to find the d*** code in the page than have to go digging around in some half-a** layered architecture wondering where the h***. is the piece of code causing the error. "

Clearly he prefers spaghetti over layered design and is probably not aware of the Go to Definition feature or many other IDE features in VS 2005 that make this so much easier.
I don't agree, but that's not the point. You have to try it out yourself to make up your own mind.

Imar
On Thursday, July 12, 2007 11:02:38 AM Navdeep said:
Hi Imar,

What are your views on using Interfaces,Abstract,sealed classes while designing architecture. The project magnitude may be medium to complex. Lot many people rely on them. Other use them religiously because they feel they should be used . Your thoughts.

Thanks,
Navdeep
On Thursday, July 12, 2007 11:25:36 AM Imar Spaanjaars said:
Hi Navdeep,

This is getting a bit too off-topic for me to answer here as comments on this article.

If you want input from developers and their views on this matter, may I suggest you post this in a forum like http://p2p.wrox.com ?

Cheers,

Imar
On Tuesday, July 17, 2007 12:35:49 PM Navdeep said:
Hi Imar,

I see all your xxxxManager and xxxxDB methods are static in nature. Any of these classes (from BL and DAL ) are not instantiated. Can we make these classes abstract because in current scope it seems more appropriate. Your thoughts.

Navdeep
On Tuesday, July 17, 2007 1:15:14 PM Imar Spaanjaars said:
Hi Navdeep,

What's the point of making them abstract? Why would that be more appropriate?

Imar
On Tuesday, July 17, 2007 2:58:48 PM Navdeep said:
Hi Imar,

because we are not creating instance and I don't expect to instantiate in current scope thats why I said its more appropriate ( or accurate ).
I hope am able to explain what I mean. Will that make any difference if we make them abstract.

Navdeep
On Tuesday, July 17, 2007 3:31:23 PM Imar Spaanjaars said:
Hi Navdeep,

It seems strange to make them abstract, which seems to indicate that a developer should inherit from it.

Instead, if you're using C#, you can mark the *classes* as static, which prevents developers from creating instances of it.

Cheers,

Imar
On Tuesday, July 17, 2007 4:44:38 PM Navdeep said:
Hi Imar,

Let me not distract you towards making them "abstract".
What I mean is , have you intentionally left classes without making them static as suggested above.

Navdeep
On Tuesday, July 17, 2007 5:18:01 PM Imar Spaanjaars said:
Hi Navdeep,

No I haven't. You can easily add it though.

Not much risk of a developer creating an instance of them as they don't have any instance method. However, making them static makes the purpose of the class a lttile clearer.

Be aware that VB.NET doesn't support this.

Cheers,

Imar
On Tuesday, July 17, 2007 5:27:25 PM Navdeep said:
Hi Imar,

Thanks for clarifying. I was talking about the same *clearer* things.

Navdeep
On Tuesday, July 17, 2007 5:32:20 PM Imar Spaanjaars said:
I understand. I just didn't agree that making them abstract would make things clearer.... ;-)

Imar
On Wednesday, July 18, 2007 8:31:34 AM Benyamin said:
Dear.
This is good article.
Question????!!!!
I not study depth of article, but if don't mistake you use of stored procedure .
so in content your article, you say, with this way transparent DBMS type.
please help me, if use of store procedure, not limit to change DBMS?

!!!???(Use of stored procedure = Limit to change DBMS)???!!!

On Wednesday, July 18, 2007 8:50:17 AM Imar Spaanjaars said:
Hi Benyamin,

Yes, correct. In the current design, the DAL is tied to SQL Server. However, it's relatively easy to rewrite the DAL for a different database (one of the design goals of the application's architecture) or make it generic using in-line SQL.

Cheers,

Imar
On Thursday, July 19, 2007 5:59:10 AM Andrew Duffy said:
Imar,

My comment is in regard to Quick Doc 416. It was a great article concerning OOA introducing the core concepts at a great beginner level.

I'm looking to find a similar article at the same level concerning SOA architecture covering topics like service interfaces, proxies to those services, the actual services themselves etc.

But every article I find goes into too deep bringing in web services and web service proxies, .NET remoting etc.

I would love to read a basic SOA ASP.NET 2.0 tutorial for beginners allowing me to write an SOA application in it's most basic form. Like you've done for OOA but this time SOA!

Have you seen any around or do you have plans to write one?

Thanks and keep up the great work.
On Thursday, July 19, 2007 6:35:04 AM Imar Spaanjaars said:
Hi Andrew,

Sorry, no, I don't know of any tutorials in this area. Maybe other readers of this thread have some suggestions?

And I also don't have any plans to write articles about it in the forseeable future.

Sorry,

Imar
On Friday, July 20, 2007 11:17:53 AM Neil T said:
Hi Imar...read your articles and built a little meeting creation web app to test them out (sites with mutliple entry points and multiple buildings, multiple meetings with room bookings, external visitors and staff, all with repeat, edit, delete (one/all meetings, room bookings, visitors, staff) etc and it worked out very nicely.

I especially liked the simplicity of the classes that the layering gives and the way it made my brain restrain itself at one level, before going onto another! I also appreciated that "lightness of touch" and clarity of thought that the whole thing gives.

Many thanks for putting this on the web.

On Friday, July 20, 2007 11:50:53 AM Imar Spaanjaars said:
Hi Neil,

Glad you like my articles. Even more so because you were able to create a working application out of them....

Cheers,

Imar
On Friday, July 20, 2007 12:25:18 PM Navdeep said:
Hi Imar,

If I have to change th UI from webforms to winforms. I will have recode UI. How can we abstract UI from other layers, like code for buttons (like add, modify, delete), Loading data into combo boxes/list boxes/DataGrid views.

Navdeep
On Friday, July 20, 2007 12:42:56 PM Imar Spaanjaars said:
Hi Navdeep,

I don't do WinForms much, so I cannot really recommend anything, other than looking into MVP (Model View Presenter) or MVC (Model View Controler) patterns.

The patterns and coding practices discussed in this article series are applicable to Winforms as well

Cheers,

Imar
On Friday, July 20, 2007 12:57:12 PM Navdeep said:
Hi Imar,

If I cut short my above comment to
"How can we abstract UI from other layers, like code for buttons (like add, modify, delete), Loading data into combo boxes/list boxes/DataGrid views."
What are your views ?
Is MVP/MVC are the best approaches ?
I am typically looking for abstraction of UI .. loosely coupled..

Thanks,
Navdeep
On Friday, July 20, 2007 1:05:24 PM Imar Spaanjaars said:
Hi Navdeep,

This whole article *is* about separation of layers. Everything except the web front end (e.g. BO, Bll, and Dal) can be used as is in a Windows application.

You can use the same techniques to get data from the underlying data store and bind it to, say, a DataGridView in a WinForms application

Imar
On Friday, July 20, 2007 1:20:02 PM Navdeep said:
Hi Imar,

Can you please quote a small example, targeting just a UI.

For eg, In winforms, I may need enabling / disabling of few text boxes or buttons while performing add/undo. There is a chance that I may tightly couple the code to achieve this.

Navdeep
On Friday, July 20, 2007 1:24:21 PM Imar Spaanjaars said:
Hi Navdeep,

Why don't you try it out yourself? It's really similar. You can things like this

btnSave.Enabled = false;
// Do stuff here
ContactPersonManager.Save(myContactPerson);
btnSave.Enabled = true;

to stop someone from clicking the Save button during an update.

Simple example, but I hope you get my point. Just experiment with it....

Cheers,

Imar
On Friday, July 20, 2007 2:01:59 PM Navdeep said:
Hi Imar,

That snippet is just fine with me.
Its may go bit off topic here. I have posted similiar query on p2p.wrox.com and had some good inputs from Peter. If you can spare some time and comment there.

http://p2p.wrox.com/topic.asp?TOPIC_ID=63095

Please delete the comment if you feel inappropriate here.

Navdeep
On Friday, July 20, 2007 2:03:53 PM Imar Spaanjaars said:
Hi Navdeep,

I was just going to suggest to move this discussion to the Wrox site because it's indeed a bit too off-topic here, but you beat me to it ;-)

Cheers,

Imar
On Wednesday, July 25, 2007 7:32:54 AM Muhammad Zeeshanuddin Khan said:
I have a different condition and want to apply your prescribed methodology.

I am developing the solution for different regions.

For example I have the Books and Languages table

--------------------------------
Languages
--------------------------------
Id
EnglishName
NativeName
Direction
IsVisible
--------------------------------

--------------------------------
Books
--------------------------------
Id
EnglishName
IsVisible
--------------------------------

Now I want these books translation in different Languages

--------------------------------
BooksNative
--------------------------------
BookId
LanguageId
NativeName
--------------------------------

Now this comes up.

Can you tell me how can I make there Business Objects.

Two BO Like Books And BooksNative
or
Just Make One the combination of Books And Books Native.

Did you get?

Waiting for your quickest solution.

Regards

Muhammad Zeeshanuddin Khan
On Wednesday, July 25, 2007 7:39:14 AM Navin said:
hi,
This Article is Good,

I have a problrm, if u can solved its nice to me.

I have a Combo box, a lable and a DetailView, Now i want to do that when i select  anyitem from Combo Box, the lable will display that selected item and also the Detail View Show the detail of that selected Item. How can i do ......?
On Wednesday, July 25, 2007 7:44:14 AM Imar Spaanjaars said:
@Muhammad

Please don't "wait for [my] quickest solution"; you could easily wait for ever.... ;-)
This is getting a bit too off topic for me to answer here as a comment on this article. Please look elsewhere, like a forum as the one at http://p2p.wrox.com.

@Navin

Same applies to you; too off topic, so may I suggest you try a forum like http://p2p.wrox.com

Cheers,

Imar

On Tuesday, August 14, 2007 12:11:14 PM Jagdeep Chawla said:
Your article is fantastic. I have implemented the same in my new project.I am working with a company in chandigarh. I am facing a problem. I have a "Author" Class and "Report" class. I have defined properties also. Now my client requirement is to show in a grid author information along with the name of report written by him. Report name property is defined in report class. i have defined a variable reportlist in my author class. But i can bind one author object to gridview. Either i have to define a name property in author and can work with no problem . but Report name will then come twice in author class and report class

What should i do?
Since i have taken the step to implement this project so i am more responsible. So I have one grid view , i want name of report in Author Grid corresponding.

Pls help me to implement the object orientation.
On Tuesday, August 14, 2007 12:38:08 PM Imar Spaanjaars said:
Hi Jagdeep,

Take a look at my replies from  3/1/2007 6:24:21 and 4/16/2007 8:25:03 in part three of this article: http://imar.spaanjaars.com/QuickDocId.aspx?quickdoc=420

It explains the basic idea for working with nested objects.

Imar
On Thursday, August 23, 2007 2:28:17 AM Clever Almeida said:
Hi Imar,

I am using your code and I'm develeping my own grid page with table control. How can I convert generic list to table ?
I have more questions, what do you think about use datable/dataview vs generic list to filter or sort ? And performance ?


Thanks.

Cléver Almeida
On Thursday, August 23, 2007 6:09:26 AM Imar Spaanjaars said:
Hi Cléver,

When you say "convert generic list to table" what kind of table are you talking to? A DataTable? An HTML Table? And why would you want to convert a generics list to a DataTable? The whole idea is to keep strongly typed objects, something you loose with DataTables.

I am not awre of performance issues between a database and a generic list. However, you can easiliy write a program that compares the two. Performance measuring is always a good thing to do....

Imar
On Sunday, September 09, 2007 12:44:36 PM Vipin said:
Hi Imar ,
Your article is Fanatstic.It provide lots of idea to me in developing application using Generic class.

I didnt get this comment..that you replied on On Wednesday 3/28/2007 8:25:45 PM
public  AddressList  Addresses
{
    get
    {
      if  (addresses  ==  null)
      {
        addresses  =  Address.GetList(this.id);
      }
      return  addresses;
    }
    set
    {
        addresses  =  value;
    }
  }

wher should i use this
On Sunday, September 09, 2007 12:51:20 PM Imar Spaanjaars said:
Hi Vipin,

You use it instead of the existing Addresses property of the ContactPerson class. Additionally, you shouldn't load the addresses for the contact person in its GetItem method, but defer loading the addresses until they are actually needed.

Cheers,

Imar
On Sunday, September 09, 2007 2:05:07 PM vipin said:
Hi imar,
Thank you for ur quick reply.
I use this code in contact person class
but
.GetList(this.id); this shows error.

how can i solve it??if i use this property like this,is it have any advantages???

On Sunday, September 09, 2007 2:42:56 PM Imar Spaanjaars said:
Hi vipin,

First of all, .GetList(this.id); doesn't look right. On what object or class name are you calling this?

Additionally, it's hard to tell from "this shows error" what is going on. What error do you get? Where do you get it?

If you need to post more code to make your point clear, please open up a thread in a relevant forum at p2p.wrox.com. The comment feature on this article isn't the best way to provide technical support.....

Imar
On Monday, September 10, 2007 3:54:32 AM kalai said:
Nice artilce.. has give a good start for first time programmers and to those who want to get rid of spaghetti codes..

Good work Imar...
On Thursday, October 04, 2007 7:40:53 PM Tahir said:
Hi Imar,

You mentioned in the article "First of all, you can see the diagram shows "smart " classes, where the data and the operations to work with that data are located in the same class. However, I decided to use "dumb objects" with separate Manager classes instead, so we'll need to change this in the next round"

I am working with what you call smart business objects and have seperate DAL for each of them. My question is that, if you would have kept the smart classes then how would you pass data between a smart class and its DAL? If we pass BO into the DAL then that causes a circular reference. If we get back DataSet for example, and have a method in BO to fill BO from DataSet then I guess that also is not a good solution. I would appreciate if you can help me in this regard.

Tahir
On Tuesday, November 06, 2007 8:00:50 AM marco said:
I have an question for you guys. How can I use AccessDataSource instead of sqlDataSource for the gridview?
After I used AccessDataSource for my program, the updating Part didn't work.
Can anyone post the all program or any solution for me?
Thank you!
On Tuesday, November 06, 2007 9:53:54 AM Imar Spaanjaars said:
Hi marco,

AccessDataSource? SqlDataSource?? I don't think those are really the topic of this article. Try a forum like http://p2p.wrox.com.

Cheers,

Imar
On Tuesday, November 13, 2007 5:46:03 PM Scott Millett said:
Hello Imar,

Great article. You mentioned that you changed your project to use dumb classes instead of smart classes, why was this? Am I right in thinking that if you had left it as it were and you split your project up into seperate class libraries (DAL and Smart BO) it would have resulted in a circular reference problem as your Smart BO would containa reference to the DAL and the DAL would need a refernce to the Smart BO?

Also what are you thoughts on splitting projects up so that the DAL, BO and BLL are in seperate class libraries? What made you keep all your code in the App_Code folder?

Thanks
Scott
On Tuesday, November 13, 2007 6:08:23 PM Imar Spaanjaars said:
Hi Scott,

Yes, with the current setup there are no circular references.

Regarding class libraries, check out my comment from 3/11/2007 8:35:15 AM in part three of this article.
http://imar.spaanjaars.com/QuickDocId.aspx?quickdoc=420

Cheers,

Imar
On Friday, November 16, 2007 1:15:43 PM Pawel Krakowiak said:
Hi!

First of all, thank you for your article series, they surely helped me to grasp the concept.

I have been struggling with some design decisions for the last couple of weeks. I won't be talking of my objects, because yours are a perfect example.

You have a ContactPerson class, which contains a collection of type EmailAddress. Each EmailAddress has an owner, who is a ContactPerson.

One way to solve this would be to add a public property of type ContactPerson (or a method which returns an object of type ContactPerson) to the EmailAddress class. The other solution is to only include the ContactPerson's ID as you did.

Could you elaborate on why you chose this solution over the other? An obvious drawback of composition are circular dependencies, e.g. ContactPerson has EmailAddresses, each EmailAddress has a an owner which is a ContactPerson, which has EmailAddresses, each EmailAddress has an owner, which is a ContactPerson, which has EmailAddresses, each EmailAdddress has... You get the idea. :)

Supposedly the circular dependencies can be fought with lazy loading and caching, but I don't know how that would be done in order to work. Your solution (I am currently doing the same thing) is simple and works, but some people suggest composition is fine, because it goes along with business rules.

I hope all this makes some sense.
On Friday, November 16, 2007 1:18:29 PM Pawel Krakowiak said:
Sorry, Imar, new lines got removed from my comment, I don't know why. Let me know if it is unreadable, I don't want to repost as I have no confidence the new lines won't be removed this time. A preview feature would be nice to have. :)
On Saturday, November 17, 2007 10:28:43 AM Imar Spaanjaars said:
Hi Pawel,

Another, possibly cleaner, solution is to make the List responsible for keeping track of the e-mail addresses and whom they belong to.

You can create a constructor for the AddressList that accepts a ContactPerson as its owner. Internally, the list can then manage the relation between the owner and the individual addresses how it wants to (through an OwnerId for example). If you extract an interface of ContactPerson you can even reuse the same lists for other entities, like a Company.

I mainly used the ID for simplicity. The main goal for this article was showing a simple, easy to use and easy to understand design that many people could use. Of course you can always extend this model, add more complex solutions to the mix. An Owner property on the List collections certainly would make a lot of sense...

Cheers,

Imar
On Thursday, November 29, 2007 2:09:44 PM Sana said:
Hi, I have been download N-LayerDesign. There isn't the solution. What I must do to open with vs and compile?

thanks

Sana
On Thursday, November 29, 2007 3:56:05 PM Imar Spaanjaars said:
Hi Sana,

There is no .sln file. It's a simple .NET 2.0 web site. Just choose File | Open Web Site (or File | Open | Web Site) and browse to the folder containing the web site.

Cheers,

Imar
On Friday, November 30, 2007 4:50:08 PM Sana said:
Hi Imar, Thanks.

On Tuesday, December 18, 2007 11:56:57 AM Shahriar Rahimi said:
Dear Imar,
I want to implement my whole project with your methodology,but i 'm faced with these questions :

1.If i have a joind of many tables(say 5),what business object should i associate with it? I mean for every multiple join which is going to happen in my whole project(which may reach thousands) i must create a business object class to hold this data? then i will have to create thousands of business object classes in my whole project which is not a good options.

2.supposing that i have a query which returns thousands of records,i think it will be a huge burden on the server to convert all of the data to my business objects.i must iterate through thousands of records and make objects from their data and add that object to the object collection.

3.when i am going to bind my business objects to a gridview or a similar component,what happens if my business object is hierarchically complex? can the grid show that? how will the grid show my object? for example,i may have an object which contains a collection of of strings in it and in every cell of that collection there may be another collection embedded.what happens in such a situation? how is the grid gonna show my complex object?
On Wednesday, December 19, 2007 6:31:14 AM Imar Spaanjaars said:
Hi Shahriar,

Indeed you probably don't want to create thousands of objects. Instead, look at concepts like server side paging and "lazy loading".

With deeply nested objects, you'll have some troubles, as explained in the article. You can use one object's collection in, say, a GridView row and then use that collection to bind to another nested Repeater for example. However, this will quickly become difficult to manage with large and complex object hierarchies, especially when editing is involved.

Cheers,

Imar
On Wednesday, December 19, 2007 7:11:35 AM Shahriar Rahimi said:
Dear Imar,
What is the best way to bind a simpler object to a grid? and what is the best way if we want to edit it?  
how is the editing,sorting and paging implemented with this approach?
suppose that we have an object with two properties and a collection inside it.
Best Regards
On Wednesday, December 19, 2007 7:37:31 AM Imar Spaanjaars said:
Hi Shahriar,

You can bind to a child collection in the DataSource property of the nested data-bound contol. E.g.:

<asp:Repeater ..... DataSource='<%# Eval("EmailAddresses") %>' ... >

where the Repeater is placed inside another Repeater and EmailAddresses is a collection of the parent object being bound to the parent control.

Cheers,

Imar
On Wednesday, December 19, 2007 7:44:25 AM Shahriar Rahimi said:
Dear Imar,
Sorry to ask you so much questions.But,is there a good way to implement sorting,paging and editing for example in a grid?
On Wednesday, December 19, 2007 8:00:28 AM Imar Spaanjaars said:
Take a look here: http://imar.spaanjaars.com/QuickDocId.aspx?quickdoc=428

If you have more questions, can you please post them on a forum like http://p2p.wrox.com?

Imar
On Saturday, December 22, 2007 5:17:13 PM SR said:
Hi,
It's maybe an ot, but I would like to know if it's possible to declare within a business object a XML property (field).
I currently have a bo that looks like that

private string _myname;
private string _mysurname;
public string MyName
{
get {return _myname}
set {_myname=value;}
}
etc..

And I don't know if it's possible to add a xml field within this BO

private XmlNodeList _myxml
public XmlNodeList MyXml
{
  get {return _myxml}
  set {_myxml}
}


Sorry if I m out of topic.

On Saturday, December 22, 2007 5:34:55 PM Imar Spaanjaars said:
Hi SR,

Sure you can. Have you tried it?

Imar
On Saturday, December 22, 2007 5:43:45 PM SR said:
Yes I did, but I try to get the content from the MyXml , I only get commas as values (,,,,,,,) .

When I insert breakpoints with VS2008, I can see the field with the correct values (it's visible inside the InnerXml key) (it's a rss feed that I load from a website).

To be more clear, I use the N-layer within a WebService and I get when I call alert(myResult.MyXml) just ,,,,,,, as value.

Do I miss something ?
On Saturday, December 22, 2007 5:47:04 PM Imar Spaanjaars said:
Difficult to tell without seeing your code.

Maybe you can post this on a forum like http://p2p.wrox.com?

Imar
On Saturday, December 22, 2007 7:10:15 PM SR said:
Imar,
It's done.. (hum hum.. if you have time before the holidays ;-) ) here's my topic http://p2p.wrox.com/topic.asp?TOPIC_ID=67812
By the way, I wish you the best for the new year.
On Tuesday, December 25, 2007 3:29:59 PM guaneme said:
Great article and I'm impressed with the patience you answer all questions.
Can't wait to share this. Thanks.
On Friday, January 04, 2008 12:14:54 PM prakash said:
hai so good
On Friday, January 04, 2008 2:57:48 PM Kader said:
Imar,
A good article.. well explained.
I do have a tiny question. When displaying my list of contacts, i need to show the contact no's as well at the same time (and not on the click of a button). One way of doing this is to execute the GetList method on the ContactPerson and when addng each ContactPerson to the grid (unbound grid) to call the GetList on PhoneNumber. However,  this would mean 2 trips to the database for each ContactPerson :-(
The only other option is to use a join onto the PhoneNumber table for the SELECT query in GetList for contact person... its merely for display purposes.

Any suggestions ?

Thanx
On Saturday, January 05, 2008 12:14:08 AM Imar Spaanjaars said:
Hi Kader,

You could load the base data and the phone number details in one fell swoop in a single stored procedure, and then bind the numbers grid to the parent grid (inside an ItemTemplate for example), using something like:

<asp:GridView ID="NestedGridView" DataSource='<%# Eval("PhoneNumbers")'>

This binds a nested GridView to its parent's PhoneNumbers property.

Hope this helps,

Imar
On Saturday, January 05, 2008 1:47:26 AM Hans Valley said:
I am mainly a business systems architect. I am learning a bit on .net 2.0 mainly to be able to ensure that our applications are written with the proper architecture (many programmers lack in arcitectural knowledge and in understanding the need for clear architectures). Anyway, your articles not only demonstrates good architecture but also shows a good way to implement this architecture in .net 2.0. Many similar articles appear to me to have significant shortcomings and are also very old (.net 1) and often thus not longer appropriate. You really have your act together, and you are an excellect writer too. Good work. Would be interested in your view of best use of the .net DataSet.
....Hans Valley
On Sunday, January 06, 2008 3:22:01 PM Quan said:
Hi,
I have read your article. It is so cool. I am a newbie to .NET and ASP.NET. Therefore, I find it really useful to me.

However, I have a question about relationships among objects. In fact, in database, we have relationships among tables and manage them using key.

Do we need to manage the relationships among objects (which are images of database tables)? And how to implement?

.Net is brand new to me. Hence, if my question is too stupid to you, please dont mind.

If you have some comments, advices on my question, please post them or woul you please email me?

Thank you so much.

On Sunday, January 06, 2008 4:36:38 PM Imar Spaanjaars said:
Hi Quan,

You may want to read parts 2 and 3 of this article series as well. The sample application uses keys / references to keep track of which phoneumbers, e-mail addresses and addresses belong to which person.

Imar
On Friday, January 11, 2008 8:27:05 PM Tarique said:
Hi,

I have been developing ASP.Net applications for 2 - 3 years and have recently started taking an interest on the software architecture aspect and how to layer and separate the code. I have read several articles on the web about it and finally found yours.

Your design is the most simple, straightforward and elegant one i've seen. I found the design more elegant and straightforward than Scott Mitchel's 3-tier tutorials ((http://www.asp.net/learn/data-access/)) using Table Adapter & Typed Data Set although it probably takes less development time than your design.

i hope to use your design/architecture when i (hopefully) design my first application.

Thanks for writing it.

And how do you think LINQ will change the n-tier section? Can your above 3 tier design be adapted to use LINQ ?

Also, I went through Scott Gutherie's tutorial on LINQ. One thing i noticed odd was that they were doing custom validation in the data layer/LinqToSQL when saving the changes. So it looked like Business layer rules was being shifted to the data access layer. Also, since i have started developing web applications, one of the important rules everyone/every website has said is to keep the SQL statements in stored procedures so that they are separate from the .Net Code. But with LINQ, now its merged together. Do you think its a good idea?

I would love to hear your comments about the above things and any other software architecture advice you can give me.

And thanks again for writing this article.



On Sunday, January 13, 2008 10:52:17 AM Imar Spaanjaars said:
Hi Tarique,

LINQ *could* be used in all three tiers, but personally, I would try to avoid it in the presentation tier. Granted, it's easy to bind a GridView to a LINQ query, but once you start doing that, you'll get in troubles when your model changes. Extending the DataContext class with additional methods would, IMO, be a good and maintainable solution. You can then calls these methods directly on your DataContext class.

Regarding the time it takes to implement my design: you can minimize the time it takes to write the code by using code generators. I do that a lot which results in better, more stable code that takes less time to write.

With regards to stored procedures: you can still use them. It's easy to map LINQ actions (inserts, updates and so on) to custom stored procedures. You can do this on the Object Relational Designer in Visual Studio.
However, IMO, SQL is *not* merged with LINQ as it is in other data technologies. Since LINQ generates the SQL for you, you don't have to bother with it. When you make a change to the underlying database, you change the LINQ model which in turn might result in broken queries (that can be checked at compile time). However, you don't have to manually change SQL statements when using LINQ.

Hope this helps.

Imar
On Thursday, January 17, 2008 5:22:50 AM Tarique said:
Hi Imar,

Which code generators do you use ?

Thanks,

Tarique
On Thursday, February 07, 2008 3:20:05 PM kurt schroeder said:
I am also interested in which code generators you use. And I agree with many here (again) that this is the best artical on this subject i've ever seen!

thanks
KES
On Thursday, February 07, 2008 9:06:24 PM Imar Spaanjaars said:
Hi Tarique and kurt,

Please read some of my comments on this article and the post about My Generation. At the moment, I use a mix of My Generation and custom built code generators....

Imar
On Monday, February 25, 2008 8:33:41 PM Hendrik said:
Hi Imar,
thanks a lot for this article, completely based my website on this design. It's very fast as to performance and very flexible as to coding/designing. If you're curious, just have a look: http://www.automeetjesland.be
On Tuesday, February 26, 2008 7:42:55 PM Imar Spaanjaars said:
Hi Hendrik,

That's great to hear. Glad it worked so well for you.... The site looks nice...

De hartelijke groeten, ;-)

Imar
On Friday, February 29, 2008 1:44:39 PM Vladimir Kelman said:
Hi Imar! I like your simple and structured approach to generating DAL and the way you presented it. To me, it's much better than messing with generated ADO.NET Data Adapters/ Data Sets. Also, for business layer custom classes and generic lists of those classes are clearly better than Data Sets, which mimic database structure instead of representing domain logic. Please read an excellent "Foundation of programming" article written by Karl Seguin http://pro-thoughts.blogspot.com/2008/02/foundations-of-programming-by-karl.html.
He expressed similar ideas on N-Tier programming in .NET. There are some ways to further tweak your approach. Your "DB" classes could probably implement the same IDataAccess interface, because their main method signatures are the same. I would also think about making a generic DataAccess&lt;BusinessClass&gt; class. With Reflection, BLL could ask DAL to return an appropriate BO object passing [part of] BO class name as a string parameter... Again, I like your approach.
http://pro-thoughts.blogspot.com/2008/02/n-tier-with-aspnet.html
On Friday, February 29, 2008 6:37:45 PM Imar Spaanjaars said:
Hi Vladimir,

Sure, you could add lots of extra stuff. Interfaces, base clases, inheritance, object serialization, moveable objects etc etc etc. However, the main goal of this design is to keep it simple and practical. The more stuff you add, the more complex things will become, and the fewer people will appreciate it.

You may want to take a look at the CSLA framework for a lot more ideas on how to extend a BO framework.

Cheers,

Imar
On Friday, February 29, 2008 9:20:56 PM Vladimir Kelman said:
Thanks, Imar! Yes, I know that Rockford Lhotka is very high-regarded programmer. Hopefully, I'll read his book sooner or later. I have to finish reading your article first, though :)
On Thursday, March 06, 2008 8:21:14 AM Vladimir Kelman said:
Hi Imar!
I have just written extensive comments on your excellent article and the following discussion in my blog at http://pro-thoughts.blogspot.com/2008/02/imar-spaanjaars.html.
On Friday, March 07, 2008 5:33:29 AM Greg said:
Hi Imar!

I really think that code-generation is a bad idea. You end up with too much code that is hard to maintain and change.

I use a tool called Diamond Binding that does definition generation. It makes very light objects and maintains all the code for me. Its free as well: http://dunnchurchill.com

I also liked the CSLA approach.
On Friday, March 07, 2008 4:12:18 PM Vladimir Kelman said:
Greg, what makes me nervous with things like datasets is the fact they imply database-driven design. I strongly feel that design should be domain-driven. You're getting familiar with business logic (domain), then you create your [prototype] objects and define relationships between them. Only then you design database to be compatible with business layer. Business layer (domain) rules and dictates. Data persistence is just one [technical] aspect among others. With "The MSDN Way" (http://codebetter.com/blogs/karlseguin/archive/2007/11/26/foundations-of-programming-part-1-introduction.aspx) you start with database and your business objects looks like very like database tables kept in memory. They even called DataTables! From what I saw on their page, Diamond Binding doesn't impose its logic on you as much as datasets/datatables do, but it still looks like database is first, business objects are second, doesn't it?
What I liked most in Imar's example is the fact he designs business (domain0 objects first. I guess, NHibernate O/R Mapping tool is so popular also because it just a mapper, allowing you to specify how your business logic should be mapped to database tables for storage. It doesn't try to tell you how your business objects should look like.
On Saturday, March 08, 2008 10:07:32 AM Imar Spaanjaars said:
@@ Greg: I don't agree that code generation is generally a bad idea. Even with other frameworks like CSLA, code generation can be very useful. CSLA requires a lot of repetitive code, so smart code generation tools can really save you a lot of development time.

@@ Vladimir: Thanks for your post., Looks like a throrough analysis....
On Thursday, March 20, 2008 11:28:13 PM Mohamed Benadia said:
Hi
this is a grate  and very useful article.
Thanks
On Monday, March 24, 2008 12:19:06 AM George said:
I have never used the class designer before and I'm finding this a bit confusing. All the Microsoft tutorials (videos and data tutorials) I have seen now exclusively use DataTables and TableAdapters (in .xsd dataset files) to access data. You can optionally create a BLL (as in
Scott Mitchell's tutorials) to get 3-layers.

I know you briefly mentioned the differences in this article but I don't quite understand.  What exactly is the difference between the 2 methods and regarding 'rapid development' which one is quicker to implement?

With this method do you have to write all the code yourself (i.e insert/update/delete code)?

As you do with the DataTable wizard can you point the class designer to a database table to create your base classes or do you have to enter all the properties manually?

Is it good practice to use at least 3-layers for all .NET projects no matter how small? I'm talking of proper production applications.

On Monday, March 24, 2008 8:59:44 AM Imar Spaanjaars said:
Hi George,

Yes, with this model you need to write most of the code yourself. However, it's relatively easy to deploy code generators like My Generation to generate most of the code for you.

The model works well for both small and medium sized web sites, and can even be used in large sites. However, you need to judge for yourself. If you have a simple Homepage type of web site with static HTML and a single contact form, it may be overkill. I use the concepts in my own web site as well, to manage content, users, photo albums and so on.

Bottom line: there is no silver bullet. You need to try out the different techniques and see what you like best.

Cheers,

Imar
On Monday, March 24, 2008 11:55:21 AM George said:
Imar

I have downloaded the My Generation software and now having a look.

Many thanks for the article and responses.
On Friday, April 04, 2008 10:13:12 PM thampister said:
Simply wow! Lucid explanation and a very real example that can be used as a starting point for real world apps - thanks a lot!
On Tuesday, April 08, 2008 3:52:38 PM Ferdy Christant said:
A while back I found out about your n-tier ASP.NET article series. I really enjoyed them and learned a lot from them.

I'm an experienced software developer, but fairly new to the .NET platform. Therefore, I wanted to gain some experience and defined a home project. It's called Blogo.NET, a Blog application. I reused a lot of the lessons I learned from your articles, yet there are also a few differences:

- My data access layer uses LINQ
- I have developed a full "production-ready" application, not just a simple example to demonstrate the techniques

Anyways, I just wanted to thank you for publishing such a great series of articles. If you want to find out more about my project, you can read about it here:

Project homepage
---------------------
http://s3maphor3.org/blogo.net/

Detailed article about the development
---------------------------------------------
http://ferdychristant.com/blog/articles/DOMM-7DDFWT

kind regards,

Ferdy
On Tuesday, April 15, 2008 10:33:42 AM Chuck said:
Imar,
I am using the concepts in your articles to develop an application. I am new to programming so please be patient with me. I have a class design question for you. I have two database tables Software and CISSoftware. Both of these have their own classes named Software and CISSoftware. After coding up the classes and developing the DAL, I have noticed that CISSoftware uses many of the same variables and properties like Software. I have been thinking that a better design for me would be to implement inheritance and make Software the base class whereas CISSoftware would be the derived class. CISSoftware could then be the more speciliazed class with variables such as Version, ApprovedDate, etc. My question is this: How would I go about implementing the DAL and BLL for a derived class? My understanding of inheritance is that you reuse properties (or class state) from a base class in a specialized class. So, when coding up my DAL, would I populate both the Software and CISSoftware class variables with values? Your articles describe a very basic way to place a class in a particular state. An example of a base and derived class would help me learn OOP design. Thanks!
On Tuesday, April 15, 2008 6:46:53 PM Imar Spaanjaars said:
Hi Chuck,

There are many different ways to do this. First, you could make Software abstract, and do all the implementation in child classes like CISSoftware. Alternatively, you can have each class fill its own data, where CISSoftware can call something like Fill() in the base class to load the parent data.

Search Google for database inheritance. You'll find many useful articles like this one: http://www.ibm.com/developerworks/library/ws-mapping-to-rdb/ that discuss the pros and cons of each solution so you can determine the best strategy for your situation.

Cheers,

Imar
On Tuesday, April 15, 2008 6:48:24 PM Imar Spaanjaars said:
Hi Ferdy,

Thanks for posting the links, and thanks also for linking to my articles from yours. I'll try to put a link back to your site or article ASAP, hopefully this weekend.

Cheers,

Imar
On Thursday, April 17, 2008 4:51:55 AM Pankaj said:
Hi its good for N-Tier Architecture
On Thursday, April 17, 2008 8:39:07 PM Juan said:
Hi Imar! I think your tutorial is excellent. In my designs, I create a Fachade class in the DAL. The function of this class is hide the behavior of the BD classes, and make that the bussines logic only calls to a AD class (the fachade before determinate what is the BD classes needed)

What do you think about this concept???

Thank you a lot!!
On Thursday, April 17, 2008 9:31:34 PM Imar Spaanjaars said:
Hi Juan,

Hard to tell without seeing any code or detailed explanation...

Imar
On Friday, April 18, 2008 2:00:47 AM wahyu said:
Great article. Our developer team is also using this kind of architecture (BO, BLL, DAL) for our application development. We like it very much, but  I see an issue. How do you implement polymorphism in the architecture where you  only have "dumb classes"? How do you manipulate a subclass using the reference of super class? should I extend the BLL classes since the methods are in there or the BO classes as the object it self.

thanks
On Friday, April 18, 2008 6:55:53 AM Abdul Kalam said:
Hi imar,

I am implementing application on the same cocept which you have done. Till now application is working well. I would be wondering if you can provide oracle DAl for the same kind of article.

Thanks.
On Saturday, April 19, 2008 1:55:28 PM Imar Spaanjaars said:
Hi Abdul,

Sorry, no Oracle implementation available. However, the code for Oracle isn't that much different, especially when you are using stored procedures.

Cheers,

Imar
On Saturday, April 19, 2008 5:14:22 PM Abdul Kalam said:
Hi Imar,

Fine i will work it out for Oracle version. Can you let me know your code is written in which Design pattern.
On Saturday, April 19, 2008 6:08:21 PM Imar Spaanjaars said:
Hi Abdul,

It doesn't have its own pattern name. It does use other patterns like the factory pattern under the hood though. It could also make use of the ADO.NET Provider pattern and be used in other patterns like MVC.

Imar
On Monday, April 28, 2008 9:50:48 AM Ian said:
Great article, and great to see this kind of subject covered well.

I prefer to avoid putting data access logic in my shared objects, and keep my tableadapters in the DAL. I ahve a question on visibility of properties and methods when using this kind of design.

If I keep all my business classes in a class library csproj shared/referenced by the all of the client csproj the server csproj and the DAL csproj , and avoid putting data access logic in my shared objects, it seems to give me a nice clean architecture, but it's a little frustrating that everything I make visible to the DAL (in the business objects) is also visible to all - e.g. I can't have (can I?) a seperate business object constructor that is only visible to the DAL, and not let the presentation layer use it. I also find I have to make all properties of a business object visible to all layers so that the DAL can save the object to DB in its entirety - however this also means the presentation layer can then read all the properties (e.g. I might not want a client app to be able to see the ID field). I don't have to make them writable, apart from through the constructor, but sometimes you don't want client code to be able to see them all.

I think I'm after a variation on 'internal' that also includes the DAL project, but nothing else.

Is there a way to do this? Is this 'friend' functionality? I believe it's possible through attributes and compiler switches, but I was hoping for something a bit nicer in code.

Thanks!

On Wednesday, April 30, 2008 7:23:08 PM Imar Spaanjaars said:
Hi Ian,

AFAIK, you can't do this with the current visibility modifiers. Internal indeed limits visibility to an assembly, not to a namespace or a specific class.

Cheers,

Imar
On Monday, May 12, 2008 2:55:21 AM Bob White said:
Hi Imar,

Is there is a performance difference between creating a website (very high traffic ) using  SqlDataSource vs Layered approach, in your article.

Thanks for your advice

Bob
On Monday, May 12, 2008 10:16:59 AM Imar Spaanjaars said:
Hi Bob,

That's difficult to say without any actual performance measurement. The SqlDataSource control itself is pretty optimized so my guess is that it's raw performance is close to the SqlDataReader used in my code (a SqlDataSource itself can use a SqlDataReader as well).
However, other factors my influence the behavior as well: type of queries, parameters, reflection (to get the data out of the control) and so on.

My advice: write two applications using both approaches and measure, measure and measure....

Cheers,

Imar
On Friday, May 16, 2008 7:11:12 PM rishad said:
hello,
        first of all its a brilliant article, but i want to use dataset in application rather than data reader what need to changed and where,

pls can u tell me
On Saturday, May 17, 2008 8:14:46 AM Imar Spaanjaars said:
Hi rishad,

And what benefit would that give you? DataSets are a lot slower than DataReaders. If you only use them to fill your business objects, there is no point in using a DataSet instead of a DataReader.

If you insist, all you need to change is a few lines of code around GetItem, GetList and FillDataRecord. A Google search for DataSet should give you many examples on loading DataSets.

But again: I wouldn't do it....

Imar
On Sunday, May 18, 2008 5:14:50 AM Rishad said:
Hello Imar,
                  First of all I thank you very for being very prompt in you reply. Yours are very excellent articles.

I would like to ask you why you have not used any design pattern like 'command or abstract factory pattern' and where the change has to be made in order to implement it.

Where can I get a sample of project using a design pattern?
Which is the best design pattern for most these types of projects.

One more query I do have for you. If I want to use webservices in this , where do I need to make a change.

Looking forward for your reply.

Regards,
Rishad
On Sunday, May 18, 2008 8:50:32 AM Imar Spaanjaars said:
Hi Rishad,

You haven't answered my question about DataSets: why would you want to use them?

With regards to other design patterns: as I said in the intro and comments on these articles: feel free to change or adapt what you see fit. My design works in many cases, but not in all of them. Adding other patterns may add in the maintainability of the software or make it easier to switch from one database to another, but also adds in the complexity of the model in the first place. My model is easy to understand and relatively easy to maintain and as such works in many circumstances. This makes it easy for beginning and intermediate programmers to understand and use it.

But, if you see the need to make changes: please go ahead.

You may want to pick up a book on Design Patterns, like "Head First Design Patterns" (although many others are available on Amazon.com). However, I doubt you'll find "the best design pattern for most these types of projects"; you use design patterns when you need them and where you need them which means you can use many different ones at the same time.

The question about web services is too broad to answer here.

Cheers,

Imar
On Sunday, May 18, 2008 6:10:27 PM Rishad said:
Hello Imar,
                  The question about dataset is that,
when there is a large amount of data that has to be very frequently modified and saved, we need to  open the connection retrieve the data and update it and then again save it, so that will be very time consuming and network consuming task there I think in that case we need to take the help of dataset, so what do u think in that will that approach be approriate or any other way to handle large amount of data is there.

As you told we need to change GetItem, GetList etc in this project in order to implement dataset in this project but tell me how to main a single dataset all across the project to prevent back and forth traffic on the network in case of dataset.

waiting for your reply....
Cheers
Rishad.
On Sunday, May 18, 2008 7:58:03 PM Imar Spaanjaars said:
Hi Rishad,

I don't think you want to maintain a single DataSet throughout the application. A DataSet seems to defeat the purpose of this layered design.

If you're worried about performance you a) need to measure first if performance is really a problem and b) look into other techniques like caching.

I can't tell you what to change in this model to supports DataSets as, IMO, DataSets don't fit into this model.

Cheers,

Imar
On Monday, May 19, 2008 12:29:25 AM Rishad said:
Hello,
         Is there no need to use dataset in n-tier arch and could you please me how to implement this application in mvc and is there any good source to learn classical MVC architecuture, what are the benefits of MVC and which one is better MVC or n-tier architecture.

waiting for ur reply
Thanx
Rishad
On Monday, May 19, 2008 7:54:57 AM Imar Spaanjaars said:
Hi Rishad,

Please don't "wait for my reply"; you could easily wait for ever.

That said, questions about MVC are too off-topic for this article. I suggest you check out Scott Guthrie's blog: http://weblogs.asp.net/scottgu/

And no, you usually don't need a DataSet. It's the business objects that hold the data, not a DataSet. Although you could use a DataSet here and there if you need to.

Cheers,

Imar
On Monday, May 19, 2008 10:18:51 AM Vladimir Kelman said:
Rishad,
A question of using of not using DataSet sometimes resembles relligious war. Microsoft put most of examples, including N-Tier, with DataSet, because it appears an easier way at first. But more and more people who use .NET are switching to more structured approach with clear design pattern which mostly came from Java (look for "ALT.NET", read Foundations of Programming and The Code Wiki Book by Karl Seguin at http://pro-thoughts.blogspot.com/2008/03/code-wiki-book-by-karl-seguin.html).
On Tuesday, May 20, 2008 4:50:57 AM Rishad said:
Hello Imar,
                  I would like to know which is better approach is it MVC or n-tier architecture.
What are the advantages and is advantages of using these both.
which is your preference?
what you advice to me follow.

Regards,
Rishad
On Tuesday, May 20, 2008 6:16:19 AM Imar Spaanjaars said:
Hi Rishad,

Please realize this is my personal blog, not a public forum. These kind of questions are much better suited for a forum like p2p.wrox.com.

My advice: study both, read a lot about it and see for yourself what fits where. You can use both in different scenarios.

Imar
On Tuesday, May 20, 2008 9:26:20 PM Homer said:
Read your article and had a quick question:
If the "BLL" uses the same "BO" types to communicate with the "Presentation" as it uses to communicate with "DAL", won't there be an encapsulation problem?  I can imagine that I wouldn't want the "Presentation" to have access to ALL the stuff the DAL is giving me.
Thanks
On Wednesday, May 21, 2008 4:49:52 PM Rishad said:
Can we merge manager classess with their respective buisness object classes.

Is there a possibility of using Ajax with your project I mean implementing in it?

Thanx
On Wednesday, May 21, 2008 5:08:04 PM Imar Spaanjaars said:
Hi Rishad,

1) Yes. Please reread the intro of this article that discusses "smart" and "dumb" objects.

2) Why not? It's all just plain ASP.NET.

Imar
On Wednesday, May 21, 2008 6:14:05 PM Imar Spaanjaars said:
Hi Homer,

Why would that be a problem? They don't get access to each other just like that; all you do is define a data structure that is the "contract" between the three layers.

Imar
On Wednesday, May 21, 2008 6:56:20 PM Homer said:
I don't KNOW if it's a problem. :)  In my mind, though, I imagine there would be some data needed by the "BLL", from the "DAL" (like foreign keys, version columns, etc) that I wouldn't want the "Presentation" to access.
I downloaded your sample.  In my head, I don't think I would want the "Presentation" to have access to Address.contactPersonId.  Definitely, not write access, probably no access.
On Wednesday, May 21, 2008 7:20:15 PM Imar Spaanjaars said:
It depends on the design. It's not necessarily wrong to have your presentation layer access these kind of properties.

If Addresses weren't stored in a collection, how would you associate it with a ContactPerson? They only way is to set that property.

However, it's easier with a collection or another "parent" object. You can make the collection aware of its owner (the ContactPerson), so using internal logic you could update the ContactPersonId property for all the addresses in your collection. That means that when you add an Address to a Addresses collection, it's associated with the owner automatically, without the need to set a property at all.

Cheers,

Imar
On Wednesday, May 21, 2008 7:54:09 PM Vladimir Kelman said:
Homer you said, "Definitely, not write access".
But no write access just means you implement only "get", not "set" for public Address.ContactPersonId property. Or, as Imar said, treat AddressList as internal collection member of ContactPerson and do not include Address.contactPersonId field.
On Wednesday, May 21, 2008 8:02:46 PM Imar Spaanjaars said:
I didn't say that at all. Addresses would be useless as an internal type and you still need the ContactPersonId property to track the owner of an Address.

However, you can make ContactPersonId internal and let Addresses handle the association.

Imar
On Thursday, May 22, 2008 4:37:38 AM Rishad said:
I am very much amazed by you so in-depth knowledge and command in the topic, Can you please tell me the secret you hold for being so powerful programmer.

I think there are thousands of programmer but no 1 like you.
Always eager to get a brilliant reply from you.
Waiting for you reply...

Regards,
Rishad
On Thursday, May 22, 2008 5:30:16 AM Imar Spaanjaars said:
Three secrets: Google, Books and Practice...

Imar
On Thursday, May 22, 2008 10:05:20 AM RIshad said:
Thanx for your reply, always glad to see me responding.

Can you tell me what does object data source does, is it a store house for housing data objects.

Is it a disconnected model or connected one.
I came to know a lot after going through your articles.

pls eloborate your answer bcause I am not asking anything off the topic.
Your one secret i dont understand : google
No good articles or sample are there on the net expects for yours on the net, then how did u manage to learn soooooooo much?


Thanking you in advance
SRM
On Thursday, May 22, 2008 11:42:42 AM Homer said:
Imar:
Thanks for the article & taking the time with this forum.

My point is that ContactPersonId needs to be (in my mind) an external (public, get/set, ...) property when BLL communicates with DAL.  However, it needs to be internal when BLL communicates with Presentation (private, no get/no set, ...).  The foreign key is an implementation detail.  I certainly don't want Presentation changing it.  It would be the same with a concurrency column, I can't allow Presentation to change that, yet BLL & DAL must have access to it.  Did I make any sense? :)  There needs to be different 'contracts' because DAL sees data (RDMBS) but Presentation sees objects (ie ContactPerson).

BTW, I hope I don't come across as confrontational.   I enjoyed the article & it's nice that you are around to discuss it.

cheers.
On Thursday, May 22, 2008 12:43:03 PM Imar Spaanjaars said:
Hi Homer,

As I said earlier: it depends. I can think of situations where I do want the presentation layer to edit an Id property like that.
But, as I said in the intro of the article: feel free to change whatever you see fit. You certainly have a valid point for many cases.

No worries about being confrontational; it doesn't feel like that.

Imar
On Thursday, May 22, 2008 12:52:14 PM Imar Spaanjaars said:
Hi RIshad,

>> pls eloborate your answer because I am not asking anything off the topic.

I won't elaborate, as it *is* off-topic. This article is not about learning ASP.NET; it's about N-Layer design.

That is exactly what I mean with using Google: a 2 second search gives you a wealth of information about the ObjectDataSource.

I also never said Google is the only solution. You can learn a lot from reading, and trying things out.

Cheers,

Imar
On Sunday, May 25, 2008 2:30:19 AM rishad said:
hi,
    I forgot to ask you wat is the name of this pattern you are using. can you please tell me why havent you used interface or abstract classes in the example and is there a possiblility of implementing interfaces and abstract classess, can i use factory pattern to extend your example, is there a possibility?

please provide me a good link where i can get most of my doubts cleared if here it is not possible.

Thanx
waiting for u.
rishad
On Sunday, May 25, 2008 7:26:16 AM Imar Spaanjaars said:
Hi rishad

Check out my reply to Abdul Kalam  on 4/19/2008 7:14:22 PM.

I haven't used interfaces and abstract classes to keep things simple. The main purpose of this design is that everyone can understand it. If you understand what interfaces are, feel free to add them to the mix. They certainly have a place there and I often use them in applications based on this design.

The following link will get most of your doubts cleared: www.google.com

Cheers,

P.S: Don't "wait for my replies"; you could easily wait for ever. And you is spelled as you, not u.

Imar
On Monday, May 26, 2008 12:24:56 AM rishad said:
hi imar,
one more query. how can we hide the dal from the presentation layer. i.e. i dont want the dal methods to be visibile to the prentation layer and i want their access restricted to only buisness logic is there any way out to do so.

do u have any other site where i am pose many more questions regarding other than this articles
thanx
rishad
On Monday, May 26, 2008 8:39:50 PM Imar Spaanjaars said:
Hi rishad,

You could implement the Dal and the Bll in the same assembly, and then make the Dal classes internal. That allows the Bll to access them, but hides them from other layers or classes.

Cheers,

Imar
On Tuesday, May 27, 2008 6:41:53 AM risha said:
hello,
        thanx for your answer, but please tell me how to do that, how to put them in a single assembly.
Rishad.
On Tuesday, May 27, 2008 6:56:51 AM Imar Spaanjaars said:
Hi risha,

I am starting to sound like a broken record, but please STFW (use Google or another search engine) or consult a forum like http://p2p.wrox.com

My site is *not* a technical support forum, and as such I cannot help you with questions like these, especially not when they can be answered with a 2 second Google search.

Learn from my articles what they offer, learn the rest somewhere else.

Cheers,

Imar
On Wednesday, May 28, 2008 11:40:57 PM Pelle said:
This Risha character looks alot like an office joke to me Imar! .....I bet I'm not the only one laughing when reading his stuff and your reply's :)
On Thursday, May 29, 2008 4:26:54 AM rishad said:
Hi Pelle ,
               I know Pelle you are an idiot. Get LOST !
On Thursday, May 29, 2008 5:47:33 AM Imar Spaanjaars said:
Hi Pelle,

Haha, you're right. Fortuntately there's a Delete button in my comment approval system ;-)

@rishad: please keep it polite and on-topic or I'll delete your posts.

Imar
On Thursday, May 29, 2008 9:43:13 AM Chanchal Gandhwani said:
Hello,

Its a good document for basic architecture of a web application.
Keep going on making these kind of documents

Cheer !!
Chanchal Gandhwani
On Thursday, May 29, 2008 5:37:03 PM srm said:
hi imar,
            what you think which is preferable mvc arch or ntier?

On Friday, May 30, 2008 5:23:45 PM Imar Spaanjaars said:
Hi Chanchal,

You're welcome.

@srm: one does not exclude the other. You can use many of these concepts in an MVC application; it's largely the way you drive the UI that is different.

Cheers,

Imar
On Monday, June 02, 2008 8:24:56 PM Donna said:
Hello Imar!  Outstanding article and a wealth of information.  I respect that you took the time to put this toegether and then shared it with the public absolutely free.  Way to promote generosity; it has helped many as I can see in the posts.  I know it will help me.

Question -- it appears that the article was written in early '07 with hints of the "upcoming" LINQ.

1.  Now that LINQ is here, any update you have on this article incorporating its use?

2.  Can you tell me briefly where in your example would using LINQ change things?  What areas would NOT be affected?

Thanks for any assistance.  Again, I've really enjoyed going through your material.  I'd also welcome recommended reading to learn this type of thing as I've tried finding something similar and cannot.

Keep up the good work!

Donna
On Monday, June 02, 2008 9:09:38 PM Imar Spaanjaars said:
Hi Donna,

Glad you ike the articles.

At the top of each article on this site you see a Details section with details about the article. It shows that this one was published at: 01/14/2007. So, yes, before LINQ was official, in early 2007.

To see a real-world implementation of this design using LINQ, take a look at Blogo.net as linked to here:  http://imar.spaanjaars.com/QuickDocId.aspx?quickdoc=445

Cheers,

Imar
On Saturday, June 07, 2008 3:54:29 AM rishad said:
I want you to write one article using web services.
Please can u do it . plssssssssssssss.
Thank u in advance.
Rishad
On Saturday, June 07, 2008 8:23:07 AM Imar Spaanjaars said:
Hi rishad,

Sorry, no, I don't take requests at the moment.

One more time: please keep it on-topic or I'll delete your comments. This is a request and not a comment on this article. You are only adding noise for people who are interested in just this article and not your nagging. And please, STFW: there are millions of articles out there on web services.

Imar
On Sunday, June 08, 2008 7:42:38 PM Bobby said:
Just wanted to tell you that your article is great! Very detailed and well written. Thanks for taking the time out to do it. I wanted to especially thank you for offering the MyGeneration templates. That was a real time saver for me.

Have you or do you soon think you'll be creating some articles around LINQ? I'd love to see your take on implementing that new technology.

Also, I haven't done much but write some small sample code for LINQ but do you think that MyGeneration can be used to generate LINQ code?

Thanks again,
Bobby
On Sunday, June 08, 2008 9:33:43 PM Imar Spaanjaars said:
Hi Bobby,

Have you seen this: http://imar.spaanjaars.com/QuickDocId.aspx?quickdoc=445 ?

It links to another project that uses my design in combination with LINQ.

It may take some time before I get to write new articles on this web site. But, LINQ is high on my list.

You can use My Generation to create LINQ enabled code. In fact you can pretty much generate anything you want with it. However, I am not sure if there is a point. The LINQ designer does much of the hard work, so I see a tool like My Generation only useful to create "extension" methods to the DataContext class for example, to generate methods you often need.
Of course you can still use the tool to generate the UI or other parts of your application.

Cheers,

Imar
On Tuesday, June 10, 2008 1:36:04 PM Khalid said:
Hi Imar,
The article looks great. one question.
When we have multiple tables, and trying to join them in data access layer the result becomes very slow, and some time throws exceptions related to database connections!, is there any tip for this?

thanks

On Thursday, June 19, 2008 7:05:00 AM kalpana said:
hai ! why we can't drag the controls in the form ,why we can't place two panels simultaneously in the design form of ASP.NET 2.0
On Thursday, June 19, 2008 7:09:52 AM Imar Spaanjaars said:
Hi kalpana,

First of all: you can. Secondly, I see no relation to the original topic of this article: N-Layer design....

Imar
On Thursday, July 03, 2008 6:26:43 AM Daniel Roberto Villarreal Treviño said:
I am only 3/4 through part I,

I am beginning programming, in a big Software company, as part time work, part time Study.

I look up to guys like you, who share knowledge.
Thanks for setting the example to us all!!
On Friday, July 04, 2008 8:42:25 PM Imar Spaanjaars said:
Hi Daniel,

You're welcome; glad you like the article series (or at least 3/4 of the first part ;-) )

Cheers,

Imar
On Thursday, July 10, 2008 7:59:58 PM Raja said:
Good article.

Also for 4-Tier architecture, see http://dotnetfunda.com/articles/article18.aspx

for 3-tier architecture, see http://dotnetfunda.com/articles/article71.aspx
On Thursday, July 17, 2008 12:50:20 PM Samir Nigam said:
After successful implementation of your Layered Architecture in my project, now i want to Integrate LINQ for asp.net 3.5. can you give some suggestions regarding it?
On Thursday, July 17, 2008 1:42:46 PM Imar Spaanjaars said:
Hi Samir,

Take a look here:  

http://imar.spaanjaars.com/QuickDocId.aspx?quickdoc=445

Imar
On Friday, July 18, 2008 4:45:50 AM Samir Nigam said:
Thanks Imar.
On Monday, August 11, 2008 8:21:17 PM Marcos Ford said:
Hi. I have a question.
What about if I need to complete a grid with a lot of rows, and each of them are objects like "sales". Supose that this sales has a lot of objects inside, like customer and lines. This grid show only some atributes of each object.

The problem is that: if I want to use an object design, I need to create each sale, calling the database many times, opening and closing connections (one for each object).
Other posibility is create a store procedure that returns all that I need (making the neccesary joins). But here I am not using an object design, only I make a query to database that returns a datatable and  is more quickly with better performance.

Summary: filling a grid, an object design needs a lot of callings to database, what is the solution for this?


THANKS A LOT!!
On Thursday, August 21, 2008 8:21:16 AM Imar Spaanjaars said:
Hi Marcos,

That question has been asked and answered a few times before. You have a few options:

1. Lazy load properties. That is, don't load the objects until you really need them. Works great for things like picture properties.

2. Use LINQ to dynamically create "summary" objects on the fly in a read-only fashion.

3. Create your own Summary objects and load them with just the data you need.

4. Load your data through a single sproc that executes multiple SELECT statements and then create overloaded constructors for your "sub objects" so they can accept a SqlDataReader to fill the object. You can then pass the open SqlDataReader from the root object into the sub classes. IMO, that doesn't break object design, but still gives you good performance.

Cheers,

Imar
On Thursday, August 21, 2008 11:42:38 AM Nigam said:
Hi Imar. Can you enhanced your layered architecture using some advanced concepts like Interfaces & abstract classes?
On Thursday, August 21, 2008 12:11:07 PM Imar Spaanjaars said:
Hi Nigam,

Yes, you can certainly do that. To keep things simple and easy to understand, I decided not to implement this in my design. However, for more extensive object models, applying base classes and interfaces to centralize behavior certainly makes a lot of sense.

Cheers,

Imar
On Thursday, August 21, 2008 1:44:06 PM Vladimir Kelman said:
Imar, it would be really great if at some point you'll find a time to write another article showing the way to enhance your N-Tier approach with base classes / interfaces...  Everybody are busy, I understand it and not asking to do my job for free (and I bought http://www.amazon.com/gp/product/0470147563)... it's just you can do it in a very clean way and teach people again. Thanks.
On Thursday, August 21, 2008 1:52:29 PM Imar Spaanjaars said:
Hi Vladimir,

Don't count on it any time soon.... Why don't you give it a try a blog about it?

Imar
On Tuesday, September 16, 2008 8:54:54 PM Steve said:
Great article so far - (only through part 1)  I am getting back into OO development after writing procedural applicaitons in vba and vb6 since college.

At the end of part  1 I see that there is a direct relationship between classes and db tables - and this makes sense to me.

What would be an example where this would not be the case?  Part of the problem I am having with getting a grasp on the OOA / OOD is I feel like I am tying my classes too close to my table structure and find myself thinking I need a class for every table.

Thanks in advance
On Tuesday, September 16, 2008 9:12:04 PM Imar Spaanjaars said:
Hi Steve,

Although it's often the case, it doesn't have to be like that. For example, a relation between two entities can be a table in the database, but not a separate entity in the model.

Similarly, you could store data in two tables (in an inheritance scenario for example) that you load into a single entity.

If you need to store data in other tables, your objects could retrieve / store data from related tables using stored procedures or access the tables directly.

So, all in all, you don't necessarily need a 1 to 1 relation between objects and tables.

Cheers,

Imar
On Saturday, September 20, 2008 10:23:14 PM Gary said:
Hi, Imar,

I'm fairly new to ASP.NET. Question about the data. Do you just copy the two database files into the APP_DATA folder? I did this, and it seemed to work. But I also imported the database into SQL Server. Can I connect to this database as well?

THank so much
On Sunday, September 21, 2008 8:17:20 AM Imar Spaanjaars said:
Hi Gary,

If you just drop them in App_Data you need a connection string that attaches the database on the fly (with the AttachDbFilename attribute). Alternatively you can attach them to SQL Server but then you need a different connection string. This is explained here: http://imar.spaanjaars.com/QuickDocId.aspx?quickdoc=395

You can't mix the two (nor would you want to) as attaching the database to SQL Server puts a lock on the MDF files).

Hope this helps,

Imar
On Thursday, October 23, 2008 4:45:32 PM Jewel said:
This is terrific, just what I've been looking for!  I wish it were listed higher on the search results when you search for OOD n-tier.

Can you give some directions though as where to go from here?  For example, I can see all manager classes inheriting from some common classe or interface, but what's the best practice for that, can you give some hints?  Some directions on more advanced senarios will definitely be looked forward to, maybe in part 4+?

Much appreciation!

On Thursday, October 23, 2008 6:16:36 PM Imar Spaanjaars said:
Hi Jewel,

You may want to wait for the new series on this topic. Should be out in a couple of weeks, maybe more.

Cheers,

Imar
On Thursday, October 30, 2008 11:39:05 AM walter said:
Hello Imar,

Thanks for the article.  It is helping me get a handle on a project.  There is one issue I have been trying to find a pattern or method for handling in the applcation I am working on.  I have a n-tier app that the clients need to be auto updated wiht new data as other users create new records.  I have been looking for a method to push the updates to the clients from the BL to the presentation layer.  I can do a pull form the Client but that seems wasteful if there are no updates to be constantly polling the data.  Any suggestions for articles or such that address this would be helpful.  I have looked at the SQL2005 Notification service but that only will work to the BL layer not to the presentation layer.

Thanks for any help you can give.

Walter
On Saturday, November 01, 2008 9:51:12 AM Imar Spaanjaars said:
Hi walter,

Why not create some events in the Bll that are fired when something happens in the database (cache callbacks, notification services) and then notify the client UI that could register to these events?

Obviously, for a web application, you always need to polling mechanism.

Imar
On Wednesday, November 12, 2008 6:57:12 AM SAM said:
Hi Imar. Following your architecture, let there be a class Project.
corresponding collection, manager & db classes are Projects, ProjectManager & ProjectDB respectively.

There is a method GetProjects() in DB class that returns collection of projects with fields - ProjectId, Name & ParentProjectId.

Now i want Hierarchichal data from the ProjectManager.GetProjects() method to bind a TreeView Control.

Can you help me in this regards?
On Thursday, November 13, 2008 8:19:52 PM Imar Spaanjaars said:
Hi SAM,

This is a bit too off-topic for me to answer here. This doesn't deal with n-layer architecture, but with creating a TreeView and sub nodes programmatically. Try this Google search for more information:

http://www.google.com/search?hl=en&q=asp.net+treeview+programmatically

You'll find a lot of useful stuff that shows you how to create a TreeView based on custom data.

Cheers,

Imar
On Tuesday, November 18, 2008 5:42:32 AM Hemant Kothiyal said:
Hi Imar,
          I read your's article about Layered approach of designing classes. Really this very good and each to understand. I have one question, As u wrote that there are two approach of designing class i.e. Smart class and Dumb Class.
Can you tell me the limitation of Dumb class approach because i as per my view when there is more complex design (more Inheritence) then dumb class is not helpfull.
On Tuesday, November 18, 2008 6:40:34 AM Imar Spaanjaars said:
Hi Hemant,

Yes, that could certainly be true, so worth taking into account.

Then again, you could create base classes for the data containers and the *Manager classes.....

Imar
On Wednesday, November 19, 2008 5:12:30 AM Hemant Kothiyal said:
Hi Imar,
           Thanks for reply.
Can you send me some good links of Class Design using Smart and Dumb approach.

Can you suggest me some books having tips for Class design in DOT NET. specially for asp.net
On Wednesday, November 19, 2008 10:23:26 PM Imar Spaanjaars said:
Hi there,

From a reader of these articles I got a list of links some time ago:

http://msdn.microsoft.com/en-us/library/ms978496.aspx
http://www.15seconds.com/issue/011023.htm
http://msdn.microsoft.com/en-us/practices/default.aspx
http://searchwindevelopment.techtarget.com/tip/0,289483,sid8_gci1278180,00.html
http://davidhayden.com/blog/dave/archive/2005/07/22/2401.aspx

And books like:

ASP.NET 2.0 Website Programming: Problem - Design - Solution (Wrox)
Expert One-on-One Visual Basic .NET Business Objects|Rockford Lhotka|Apress|2003
Expert VB 2005 Business Objects, Second Edition|Rockford Lhotka|Apress|2006
Visual Basic .NET Class Design Handbook: Coding Effective Classes (Apress)

Additionally, you could look at the Pro series of Wrox, like Pro C# 2008.

Cheers,

Imar
On Friday, November 21, 2008 2:55:28 PM Amit Mistry said:
You made great artical.But Put validation when enter email address.
So when can not save it without @ or someother expression
On Friday, November 21, 2008 6:03:06 PM Imar Spaanjaars said:
Hi Amit,

Validation is something I'll cover in the upcoming article series on N-Layer design. At the moment, I am crossing the t's and dotting the i's so to speak so you can expect the new series real soon.

Cheers,

Imar
On Tuesday, December 16, 2008 6:09:43 AM Ray said:
Im a newbie to .NET, so please be kind. :) If I downloaded your zip file, would I be using your files in a new Website (WS) or Web Application (WAP) Project? WAP wouldnt work for me, but WS worked fine. Thanks for your great article.

Is there a way you can show us how to use individual projects in a solution as the different layers? Thanks!
On Tuesday, December 16, 2008 7:18:47 AM Imar Spaanjaars said:
Hi Ray,

It's a Web Site Project, not a WAP.

For a complete description of separating this over multiple projects, take a look at the follow up article series I have written:

http://imar.spaanjaars.com/QuickDocId.aspx?quickdoc=476

Cheers,

Imar
On Tuesday, December 23, 2008 10:58:40 PM Tom said:
Hi Imar!

First of all, great set of articles! Stuff like this is hard to find.

Assume I have a similar application to your example here except that I manage students. Assume that a student has a Name, an Address and a ClassName. If the ClassName is calculated automagically somehow in the backend (based on the student's address for example), how should the Student entity be designed so that when a user is adding a new student, they cannot enter the ClassName? Obviously the interface can simply not display the ClassName field but I'm more after the design of the Student class.

So all of the student details are available when viewing a student's details, but when editing or adding a student the ClassName is not available.

Should there be 2 Student entities perhaps? Student and EditableStudent? And therefore 2 student managers in the BLL and 2 student DB managers in the DAL?

Having a single Student class seems problematic to me as it would require passing around a partially filled Student object all over the place.

Hope to hear from you.
Cheers,
Tom
On Tuesday, December 23, 2008 11:58:35 PM Bec said:
Just a quick question about your use of application settings. The AppConfiguration class in DAL directly accesses the web.config. Is it correct to do this from the DAL class library? What if we choose to change the UI to something else and store the app settings and connectionstrings somewhere else (not in web.config or app.config)? Would it be better to somehow pass these settings from the presentation layer down to the DAL?


Thanks for the article, great work.
On Wednesday, December 24, 2008 5:04:43 PM Imar Spaanjaars said:
Hi Tom,

Isn't that just a matter of making the ClassName read only? (Or at least mark its setter as private or internal)?

Imar
On Wednesday, December 24, 2008 5:06:43 PM Imar Spaanjaars said:
Hi Bec,

Yes, that would be a good idea. I typially don't care that much as I either use a web.config file, or an app.config file. However, if you have different requirements, it's a good idea to be able to pass these settings in (as a static property on the respective Dal classes or a Helper class for example).

Cheers,

Imar
On Thursday, December 25, 2008 12:12:53 AM Tom said:
Hi Imar,

I don't believe we can mark the ClassName as readonly since the Dal will still need to set it for a Read for example. That is the ClassName needs to be set when reading the values from the DB and displaying the results to the user. I just want the ClassName to be readonly for a New or Edit Student.

I don't believe marking the setter internal wouldn't help either since the Entities are in a different assembly and are shared by the Bll and Dal (and Presentation too) and so would not be visible from the Dal.

I was thinking of having a single StudentManager in the Bll which would work with 2 different Student classes; one with ClassName (for a Read operation on the student) and another one with no ClassName at all (for Add and Edit). So one is essentially a subset of the other. What do you think?
On Thursday, December 25, 2008 10:39:10 AM Imar Spaanjaars said:
Hi Tom,

You may want to check out my new article series on N-Layer design here:

http://imar.spaanjaars.com/QuickDocId.aspx?quickdoc=476

Part 6, published somewhere next year deals with security. It shows you how to implement security in your objects. This way, you could protect the setter of your object so it doesn't allow the ClassName to be set for specific users. This example is not shown explicitly in that article, but it should give you enough ideas on how to implement it.

If you don't want to wait that long for the article to be published, you can buy the entire series right now:

http://imar.spaanjaars.com/QuickDocId.aspx?quickdoc=482

Cheers,

Imar
On Sunday, January 04, 2009 8:45:06 PM Robin Simmons said:
Hello Imar,
Thanks so much for the quick response to my earlier query about the Lookup Tables.  I mentioned I was applying your methods on Layered Applications to an project I'm currently working on.  My project uses GUID's as primary keys and I'm having a little trouble with the Save Method returning the new GUID.
I've modified the Stored Procedure as follows:
ALTER PROCEDURE [dbo].[sp_DealInsertUpdateSingleItem]
-- Add the parameters for the stored procedure here
@Id uniqueidentifier,

<snip lots of code cut by imar />

I've also modified the Save Method as follows:
Dim result As Guid = Guid.Empty
...
result = New Guid(returnValue.Value.ToString)

Any help you could give to resolve my issue is greatly appreciated.

Happy New Year,

Robin Simmons
On Sunday, January 04, 2009 9:37:10 PM Imar Spaanjaars said:
Hi Robin,

Return values are always integers; you can't return Guids using the return statement. Instead, you need to use OUTPUT parameters.

Output parameters are discussed in part 5 of my *new* series on N-Layer design when concurrency is discussed. You can read parts 1, 2 and 3 of the series now here: http://imar.spaanjaars.com/QuickDocId.aspx?quickdoc=476

Part 5 will take another month or so. If you don't want to wait that long, you can buy the full series and source code here for only $ 15: http://imar.spaanjaars.com/QuickDocId.aspx?quickdoc=482

BTW, starting your sprocs with sp_ is a bad idea: http://www.sqlmag.com/articles/index.cfm?articleid=23011&


Cheers,

Imar
On Monday, January 05, 2009 12:45:09 AM Robin Simmons said:
Thanks Imar for the OUTPUT and sp_ advice.

Will the code for your new series be ported to VB?  While the discussion, examples, illustrations and screen shots in your first series were very helpful, the code was the most helpful for me because I don't know C#, even thought I could follow the logic in the examples.  With the VB code, I could look at the code and look back at the article and see exactly what you were doing.  It would be even more helpful if the article examples were in VB.

No matter, I'm just happy there are guys like you who can write clearly and are willing to do so and put the information out there for others.

I will buy the new series once it gets ported to VB.

Thanks again for your help.

Robin
On Monday, January 05, 2009 3:08:56 AM Bec said:
Hi Imar!

This is related to Tom's Student and ClassName example.


Sharing the BusinessEntities between all 3 layers creates a problem in some cases (not in your Contact Manager example).  For example the Address business entity exposes both a setter and getter for the Id property.  This is obviously needed in the Dal to populate the data from the database but it would not make sense to have the setter exposed from the Presentation to the Bll because the Presentation layer could potentially allow the user to modify the Id and send it to the AddressManager which has no way of detecting such issues.  What if the Dal and Bll had their own Entities? The Bll could then receive a Dal Entity and convert it to a Bll version of the Entity and only expose that to the Presentation.


Regards,

Bec
On Monday, January 05, 2009 8:11:48 AM Imar Spaanjaars said:
Hi Robin,

Yes, the new series is currently being translated into VB.NET. It's about 95% done; as soon as it's ready I'll add it to the downloads section of the  new series.

Cheers,

Imar
On Monday, January 05, 2009 8:15:12 AM Imar Spaanjaars said:
Hi Bec,

Yes, you could do that. However, that would mean writing a lot more code as you need to duplicate your objects.

Cheers,

Imar
On Saturday, January 24, 2009 6:22:52 PM Erivando said:
Have to adapt this example to the database Firebird?

I need to generate the code trim Fibebird
On Saturday, January 24, 2009 11:09:34 PM Imar Spaanjaars said:
Hi Erivando,

Cool; let me know when you're done and I'll be happy to host the source here....

Imar
On Sunday, January 25, 2009 1:10:04 PM Erivando Sena said:
Thanks, Imar

I am waiting.

Erivando
On Sunday, January 25, 2009 1:13:27 PM Imar Spaanjaars said:
Waiting? I think you misunderstood what I said....

Imar
On Friday, January 30, 2009 9:05:34 PM mafioso710 said:
Hi Imar, would you like to give any example how can i implement a web inventory software using your n-tiers model ? please some ideas.

thanks.
On Friday, January 30, 2009 11:05:20 PM Imar Spaanjaars said:
Hi there,

That's way out of scope to ask / answer here. My articles show you how to set up the architecture of the application, not how to do the design of the actual business domain. That's up to you or your designers / architects / consultants. My articles give you ideas on how to implement it, but it's up to you to do the translation from your business domain to your application.

Cheers,

Imar
On Sunday, February 01, 2009 7:55:06 PM Nice.developer said:
where is the layer of work flows?
On Sunday, February 01, 2009 8:04:32 PM Imar Spaanjaars said:
What?

Imar
On Sunday, February 01, 2009 8:11:57 PM Nice.developer said:
work flow?
have you implemented work flows?
On Sunday, February 01, 2009 8:15:02 PM Imar Spaanjaars said:
No.

Apparently, nice developer refers to the way you code, not to the way you communicate. Pffff.....

Imar
On Sunday, February 01, 2009 8:19:23 PM Nice.developer said:
??
On Wednesday, April 08, 2009 12:19:14 PM abdallah mohammed abdallah said:
It is perfect
i have one question how can i use the generation template
On Wednesday, April 08, 2009 5:14:11 PM Imar Spaanjaars said:
Hi abdallah,

To get a copy of MyGeneraton and to learn how to use it, take a look here: http://www.mygenerationsoftware.com/portal/default.aspx

Cheers,

Imar
On Thursday, April 09, 2009 9:08:41 PM matt herb said:
I love the style of ASP.NET instant results.

Is there any similiar book out now using 3.5 features? (LINQ)

Love to see a similiar artcle using LINQ 2 ENTITIES also!
On Friday, April 10, 2009 10:50:41 AM satu CL said:
Thank you for your explanation. I am learning how to apply this model these days.

On Saturday, April 11, 2009 10:25:51 AM Imar Spaanjaars said:
Hi matt,

You may want to check out Blogo.net, an implementation of this model using LINQ to SQL. I think you'll find it easy to change to LINQ to Entities instead.

http://imar.spaanjaars.com/QuickDocId.aspx?quickdoc=445

Cheers,

Imar


On Friday, May 01, 2009 7:14:22 AM sandip salokya said:
hi Imar,

i downloaded your N-LayerDesign code for 2005.
it is really a nice architecture.

it is working well.

But i found 1 ERROR IN UseApi.aspx.cs. when i opened this page, and clicked on start debugging button ERROR is showing at
myConnection.open();
msg:SqlException was unhandled by user code in AddressDB.cs
error: MSDTC on server 'UNKNOWN-E6AAF13\29BB3C5C-EDF8-45' is unavailable.
On Friday, May 01, 2009 7:18:46 AM Imar Spaanjaars said:
Hi sandip,

It's not an error in the code, but an error in your configuration. You need to enable and configure MSDTC. Check out part 2:

http://imar.spaanjaars.com/QuickDocId.aspx?quickdoc=419

and search locally for MSDTC. You'll find a bunch of links that explain how to configure it.

Cheers,

Imar
On Friday, May 01, 2009 7:12:27 PM Vladimir Kelman said:
My 5 cents for MSDTC:
http://maonet.wordpress.com/2008/06/16/turn-on-dtc-access-on-xp-sp2/
http://support.microsoft.com/kb/899191/
http://support.microsoft.com/kb/817064/
http://technet.microsoft.com/en-us/library/cc753510.aspx
On Monday, May 18, 2009 6:20:15 AM Babak Mokri said:
Hi Imar,

Thank you for this clear tutorial, it is most useful. I have a question in regard to Data Access Layer class diagram. How do you make the diagram to display a method like "Delete() : bool" and not simply "Delete"?

Thanks in advance.
Babak
On Sunday, May 24, 2009 10:02:30 AM Imar Spaanjaars said:
Hi Babak,

With the class diagram designer open, choose Class Diagram | Change Members Format and then choose between Display Name and Type and Display Full Signature.

Cheers,

Imar
On Tuesday, May 26, 2009 7:51:47 AM Baba Mokri said:
Thank you very much Imar.

Babak
On Thursday, May 28, 2009 3:33:15 PM Bassel said:
Hi Imar,
Thanks for these articles, its like a crash course in N-tiers design.
my question, i did download the MyGeneration Templates you have created
and i have noticed that the template that generate Business Objects are doing some mistakes, for example
i have 2 tables:
User {userid(pk), name,etc...}
and Article{ articleid(pk), userid(fk), articletitle, etc....}

the template gave me a class for Article which looks as following:

Public Class Article
private _articleid as inteager = -1
..
..
private users as UsersList = new UserList()


and i guess this is a mistake in the template gernation code
because if you notice the table design is userid is a forign key in the article table. which means each user has many articles. not each Article has many Users.
so i should get the property Articles as ArticleList in the User class
not to have users as UserList in the Article class.

the other templates that generalte business logics and data layers are fine but i am getting errors in the generated code because of the business objects got gernerated wrong.

could you please advice. if you have another corrected version ?

Thanks


On Thursday, May 28, 2009 4:20:37 PM Bassel said:
Just regarding my previous comment, this issue is only in the VB.NET version
but not in the C# version
and the VB template that generate the Business Logic is also wrong and has the same error in checking FKs that i noticed in the BO template
On Thursday, May 28, 2009 4:40:39 PM Imar Spaanjaars said:
Hi Bassel,

I am sorry, but I don''t think I can help. Like I said here: http://imar.spaanjaars.com/QuickDocId.aspx?quickdoc=435 I didn't write them so I don't know much about them.

If you find a bug and have a fix for it: please let me know and I'll be happy to update the code I am hosting here.

Cheers,

Imar
On Monday, June 08, 2009 8:15:18 AM Tanveer Hussian said:
told me all data base basic tool
On Sunday, July 12, 2009 12:30:37 PM virender said:
hi,

Our Team developed a project with following layer with one solutions project. currently application running on one web server. but on that portal   4000-5000 user access their accounts information in one time and day by day portal performance decreasing due to user increase. so,  we need increase performance . Currently using following layer.

1. Presentation layer
2. Business Layer
3. Data Transfer object
4. Data Access Layer

For good performance we need to implement difference layer on different server . It it possible or not ? If possible then how . please help me.

Presentation layer, - Server1

Business Layer ,
Data Transfer object(DTO)- Server2
(Serialazable)

Data Access Layer - Server3

Sql Server 2008 – Server4
(Database Server already running on separate server)

On Sunday, July 12, 2009 12:43:16 PM Imar Spaanjaars said:
Hi virender,

First of all, this article is about N-Layers, not about N-Tiers. Layers usually refer to a logical separation while Tiers refer to a physical separation. You can't use the designs presented in this article directly in an N-Tier environment.

Secondly, I don't think it's necessarily true that using four physical tiers improves performance. In fact, it may result in a decreased performance because of the tier overhead. It's usually easier to scale this way but at a cost of some performance overhead.

That said, you may want to get a copy of the book Expert C# 2008 Business Objects by Rockford Lhotka. That book presents a true multi-tier architecture.

Cheers,

Imar
On Tuesday, July 28, 2009 3:37:08 PM DotNetXenon said:
Very good article. Keep up the good work.
On Saturday, September 12, 2009 3:15:10 AM Mohammad said:
Thanks for this beneficial and simple-explained article.

I have a question please. What if I placed the business objects in the parent namespace (i.e. Spaanjaars.ContactManager), would be there any disadvantages?
On Saturday, September 12, 2009 11:08:01 AM Imar Spaanjaars said:
Hi Mohammad,

Technically, there's nothing preventing you from doing that. But why would you want to do it? It feels odd to have these objects in a parent namespace....

Imar
On Saturday, September 12, 2009 5:44:03 PM Mohammad said:
Hi Imar,

Thanks for your reply.

By doing so -placing the business objects in the parent namespace- there will be no need to import them in neither the BLL nor the DAL.

However, by placing them in a separate namespace, do you mean that the parent namespace will be empty of classes. And here I have another question, in case I want to implement a facade class, where should I place it?

Thanks,

~Mohammad
On Monday, November 23, 2009 5:55:34 AM Suresh said:
Instead of dumb classes, why don't i use structs, What is the use of dumb classes.
On Monday, November 23, 2009 7:51:02 AM Imar Spaanjaars said:
Hi Suresh,

Structs are value types and typically limited in size, so they may not always be appropriate in this design.

Cheers,

Imar
On Friday, December 04, 2009 6:53:08 AM Sisir said:
Hi,
this is a very good articles which clearly describes the architecture and its very very useful. My Question is as you said that " this article was to explain an architecture that can be understood by many",Can you explain other robost / best architectures (may be complex) for both web app like websites or data  centric windows apps
On Friday, December 04, 2009 5:39:26 PM Imar Spaanjaars said:
Hi Sisir,

There are many. Searching for "design patterns" should get you a long way. Additionally, you may want to look at books such as Professional Enterprise .NET from Wrox or Expert C# 2008 Business Objects from APress for real-world implementations.

Cheers,

Imar
On Friday, December 11, 2009 11:30:14 AM Sven G said:
This article is pure gold! No comments...
On Monday, December 21, 2009 10:11:15 AM Nikhil said:
Hi,
I got the code for sample application in part 1 2 and 3 but it is missing solution file.
please reply.
Thanks.
nikhil
On Monday, December 21, 2009 7:28:04 PM Imar Spaanjaars said:
Hi Nikhil,

It's not missing as there isn't one.

Search for my reply to Sana in this article for more info.

Cheers,

Imar
On Sunday, February 14, 2010 7:33:24 AM Abhilash said:
Finally, I got the one to start with.
I really appreciate ur patience for writing this valuble article.
Thanks again.
On Tuesday, April 20, 2010 5:12:09 AM safdar hussain said:
Nice,its v helpful  
On Saturday, May 15, 2010 10:26:23 AM anil said:
hi
i have a simple doubt, im using DAL and BLL
just i want to write the value to the textbox using BLL

code:

Dim productslogic As New productsBLL()

TextBox2.Attributes.Add("value", productslogic.GetDataByname(TextBox1.Text).ToString)

when im executing the above program , in textbox2 im getting asaa(asaa is my data table name) instead of password

here im checking whether username exists or not, if exists then user password should be written to the textbox2, if user doesnt exists then message:invalid user

here im using BLL:productsBLL()
and the query for getdatabyname(@name) is
select password from asaa where name=@name

can anyone help, to get the password to textbox


On Saturday, May 15, 2010 2:16:06 PM Imar Spaanjaars said:
Hi there,

Difficult to say without seeing what type of object or data GetDataByname returns. Apparently, it's a complex object rather than a simple string as the default implementation of a class is to say its name when ToString is called. You may need to call one of its sub properties instead.

If that doesn't help, please post this on a forum such as this one: http://p2p.wrox.com/index.php?referrerid=385 in an appropriate forum. If you do post there, be sure to post lots more details and code.

Cheers,

Imar
On Saturday, June 12, 2010 1:54:22 PM namrata said:
Great.That is what i am looking for to create website having good architecture.
On Tuesday, July 06, 2010 11:23:08 AM 654 said:
89+8+
On Friday, August 06, 2010 1:23:54 PM Manu said:
Hi Imar

Your article is very interesting and I found it very usefull. I have a question about this kind of apps.

Usually my apps must have grids (or reports) wich shows information from two or more tables (joined tables). In your example, you can show all the fields from a Bussines Object in the grid but, what happen if you need fields from others tables?

Now, I use views or embeded sql querys to populate these grids but, in a Bussines objects scenario, is this the best solution? I feel that using this kind of things does not match well with an OOP aproach.

I think that one possible solution is to create classes from this views or querys and use them like a read only Bussines objects. Other solution is to use typed datatables only for the views, but this solution looks less uniform.

What would you do?

Thanks in advance
On Saturday, August 07, 2010 9:46:07 AM Imar Spaanjaars said:
Hi Manu,

Yes, you indeed have a few options:

1. Create lightweight and simple objects for read-only display. Sort of *Summary objects

2. Use something like Entity Framework or LINQ to SQL to create those objects without a lot of overhead.

3. Use typed data sets, although I find them to be a bit outdated sometimes.

4. Lots of other options.

You have to outweigh the pros and cons of each solution in your situation.

Cheers,

Imar
On Tuesday, August 24, 2010 11:28:05 PM Manu said:
Hi

Another question. In your example the collections Adresses, Phonenumbers and EmailAdresses are placed directly as public properties in the ContactPerson Class, This means: contactperson class can´t control the access to these collections (following the OO encapsulation principles). If I put a field in contactperson which contains the longer Adress of a contacperson (this is absurd, but valid for instance) , you need to check every Adress added to update that field. That could be made with a "setter" method, but if I have a collection, what can I do? How do you solve this problem in your Apps?

Thanks again
On Wednesday, August 25, 2010 12:57:46 PM Imar Spaanjaars said:
Hi Manu,

I am not sure what you mean with a "field in contactperson which contains the longer Adress".

To prevent direct access to the Address collection, you could expose it as a read-only IEnumerable of Address and provide AddAddress methods that enable API users to add an address. In AddAddress you can then do whatever you need to do.

Cheers,

Imar
On Tuesday, September 14, 2010 2:14:18 PM Aspboomer said:
hi Guru,
Guru mean teacher, i call u teacher because i have got to know a lot from your version and complete explanation to teh nalyered app. its guru's like you who encorage people like me to learna nd start with your sites , my problem is I do not have a job, i need to be expereiced in asp.net and c#, request you to send me more such examples with explanation
trust me teh day i receive my frist sal i will donate to this noble cause,


regards,

Aspboomer
On Tuesday, September 14, 2010 3:38:32 PM Imar Spaanjaars said:
Just search my site. You'll find hundreds of articles, including the 3.5 follow up series: http://imar.spaanjaars.com/476/n-layered-web-applications-with-aspnet-35-part-1-general-introduction

Cheers,

Imar
On Sunday, December 19, 2010 10:37:25 AM Tiki said:
Thank you very much for this well explained series on N-Layered apps!
On Wednesday, February 02, 2011 12:32:10 PM Owais said:
Hello Imaar,
Very nice article I'm learning a lot from this articles series,im a beginner ASP.net web developer ,i have completed my two paid web Applications and was in need for organizing my code and web project,these article series just provided me what i needed,
i just found some spelling mistakes...
just search "ad" you can replace it with "and"

Thanks..
On Wednesday, February 02, 2011 12:43:20 PM Imar Spaanjaars said:
Fixed; thank you!

Imar
On Tuesday, March 29, 2011 4:43:46 AM Mike said:
Hello Imar, Good day. Why are the addressList,EmailAddressList & PhoneNumberList initialized/instantiated inside the ContactPerson class ? What is the use ?
Also, the address lists etc. all initialize a separate List object whenever they are invoked so what is the use of initializing them in ContactPerson class ?
On Tuesday, March 29, 2011 4:53:16 AM Imar Spaanjaars said:
Hi Mike,

If you don't initialize them, you won't be able to add items programmatically. E.g. this:

ContactPerson cp = new ContectPerson();
cp.Addresses.Add(new Address() { ... } );

would fail with a NullReferenceExcpetion.

Cheers,

Imar
On Tuesday, March 29, 2011 3:03:39 PM Hector Rodriguez said:
Hello Imaar,
Are you planning to have an ASP.NET 4.0 of this code? Have a great day. Take care
On Wednesday, March 30, 2011 2:19:00 AM Imar Spaanjaars said:
Hi Hector,

Planning: yes. Time to do it at short notice: no..... ;-)

Cheers,

Imar
On Wednesday, July 13, 2011 9:05:32 PM gary said:
Hi Imar,

Again, thanks for sharing your knowledge with the rest of us. I bought 3 of your books already, (asp.net 2.0 instant results, beginner asp.net 3.5 and 4.0) and hoping that you would write a book that contains project that emphasizes the 3 TIERS of programming architecture.

Basically I'm still struggling with tier design, and how to start doing it, so hoping that I could find one of your book in the future where you will start with Data tier, then business, then presentation tier with lots of explanations for us beginners.

More power!
On Thursday, July 14, 2011 1:30:55 AM Imar Spaanjaars said:
Hi gary,

Isn't that what this series, and the follow-up series for .NET 3.5 are all about?

Imar
On Thursday, July 14, 2011 3:32:51 AM Gary said:
Hi Imar, yes, but I would be hoping for a book similar to your Instant Results where several projects are developed using the latest framework. This series is excellent though. cheers
On Thursday, July 14, 2011 3:48:56 AM Imar Spaanjaars said:
Hi Gary,

No plans for a book like that any time soon, but you may want to take a look at Professional ASP.NET Design Patterns By Scott Millett.

Cheers,

Imar
On Sunday, July 17, 2011 7:40:25 PM Gary said:
That's okay, I prefer your way of teaching. This article has opened my eyes to basics of n-tier achitecture, answered question like why are there methods in a particular class and others don't have them by your definition of 'dumb' and 'smart' class, etc. A big thank you. You really have the skill for writing great articles as seen on your books and these types of articles. Keep writing!

Thanks
On Wednesday, July 20, 2011 1:18:15 PM Abaf said:
Hi Imaar,
I have read your article ,loved it...
I have a question which is echoing in my mind...

Why you used dumb classes ,when you only need to keep data in class..
Why not create structs as dumb data carriers??
I read some on value types and reference types,and you know the performance issues...
I think struct is a better choice,can you explain ??
On Thursday, July 21, 2011 7:14:56 AM Imar Spaanjaars said:
Hi Abaf,

You could try to change them to structs and see if it works.; I haven't tried it though.

Structs do in many cases perform better. However, in applications like these you won't be working with hundreds or thousands of objects in memory at the same time, so I doubt you'll be able to measure the difference.

Cheers,

Imar
On Saturday, September 03, 2011 9:24:53 AM shabir hakim said:
Great work..
thank you very much
On Sunday, September 04, 2011 2:05:03 PM subbu said:
Hi Imar,
The very fact that this article/discussion has been kept alive since February 05, 2007 till date itself speaks volumes about your article and its usefulness... :) great job.

I haven't gone through the entire discussion in here so i might be repeating this point, kindly direct me to the relevant discussion in that case.
Here i feel the possibility of reusing the codes and modules is very minimal, the reason being any change in the database will affect the business objects (unless the dal access the data from the db and manipulates it to fit the existing bo, which might not be very elegant) and any change in the bo is going to affect the BLL and the DAL (let alone reusing the code and modules for a different app as this often undergoes a considerable change at the back end), kindly correct me if i am wrong.
The only modules that could be reusable are generic classes for e.g. functionality to export data into various formats like .doc .xls .pdf etc or in this example itself we could have another layer of generic dbUtility which can abstract the task of db connection and executing the SPs. Am i misunderstanding something? Kindly let me know your take on this...:)
--Subbu
On Monday, September 05, 2011 1:23:37 AM Imar Spaanjaars said:
Hi subbu,

Yes, you're correct. You won't be able to reuse the code in other projects; but the idea is to reuse objects. E.g. you can put all these objects in a separate class library and reference that from multiple front ends.

But this is also the reason I am using Entity Framework Code First more and more. It lets me do most of what I describe here without the need to manually update code when the database changes.

Cheers,

Imar
On Tuesday, September 06, 2011 12:15:53 PM subbu said:
Thanx for the prompt response Imar,

In your response, by saying "put all these objects in a separate class library", did u mean creating something like a dll? can you please explain the concept...? may be with reference to this project itself:) and multiple front ends means forms & browsers?

I noticed another thing... the use of enums for "types".
Wouldn't it be better to use a look-up table at the back end containing the types of contact and just have the id of the contact type in the other tables? This would give us a good flexibility to add or modify the types when required without changing any code!
Say tomorrow i want to add a type as a facebook contact or a school contact or college contact etc...i could just add the new items in the db and as soon as i do that i have it loaded on the front end too. Kindly comment
On Tuesday, September 06, 2011 12:23:18 PM Imar Spaanjaars said:
Hi there,

Yes, I meant a DLL. Take a look at the ASP.NET 3.5 version of this series here: http://imar.spaanjaars.com/476/n-layered-web-applications-with-aspnet-35-part-1-general-introduction to see how that works.

With multiple front ends I meant a web application, a desktop app, a Silverlight application, a Web or Windows Service and so on.

And with regards to enums: you're right, but it depends. I wouldn't use an enum for all countries on earth for example. But having additional domain tables does mean more overhead in coding and at run-time.

Cheers,

Imar
On Tuesday, September 06, 2011 3:38:47 PM subbu said:
Hi Imar,
Yes i get your point there on the enums.

Another question i would like to raise regarding the performance of these kind of designs is...
we fire the queries or execute the sps from the front end...then get a response from the db which is in a tabular form. Now we access these tables and convert them into the bo types in the dal, which requires looping through the table record by record and filling in different objects of the relevant class (1 record = 1 object of the class). these objects are now passed to the bll layer.
Now the bll again accesses these objects to generate the required output.
So my question is cant we by pass this conversion of the data into BOs by directly passing the tables received from the db to the BLL? Wont this improve the performance considerably? kindly comment and also let em know the drawbacks of this approach if any. I do understand that I am probably talking about clubbing the dal and the bll together in a sense. But isnt it worth the effort we save by by-passing the conversion?
On Tuesday, September 06, 2011 3:43:35 PM Imar Spaanjaars said:
You could, but it would break the separation that this design is trying to achieve, coupling your code too much with the database. The BLL could equally work well with objects built from XML or whatever.

To get a real answer to your question: do a performance analysis and see if this is a real problem for you, or if you're just getting into premature optimization.

Cheers,

Imar
On Tuesday, September 06, 2011 4:00:26 PM subbu said:
Yes true a performance analysis would give the answer...

Probably it would be a good idea to mix and match both the approaches...i.e identify scenarios which are going to return a big volume of data from the db and pass them directly to the bll and stick to the bo conversion for other scenarios. This way we could come out with a hybrid design without compromising.

cheers,
Subbu
On Tuesday, October 18, 2011 6:41:06 PM Gar said:
Hi Imar,

Following the structure of your folders, how do I fix the problem of the solution not able to see the BLL or BO folders under App_Code folder in the Imports definition?

Thanks
On Wednesday, October 19, 2011 7:10:14 PM Gar said:
Ignore my last post Imar, got it working, thanks, I supposed to use application project instead of website project.

cheers
On Thursday, November 17, 2011 12:18:25 AM Rahul said:
Hello, I like the article.
In my application I have facade layer, followed by Business layer, which is followed by DAL layer. Facade layer requires business objects as a return for provided ID to the Business layer class function. This business layer communicates with DAL and gets the list of the business object. Here I have one doubt. Where the business objects should get created. I think as it is one directional relation and Business layer is above the DAL, DAL  should not create the business objects. But based on the ID facade requires multiple business objects. so what should be design for the application.
On Monday, January 16, 2012 7:51:04 PM Kenan said:
Hi Imar,

What you have done is really GREAT!!!
How can I order PDF for both versions of Building Layered Web Applications in 2.0 and 3.5? I don't have PayPal and I really need both versions.

Thanks and all the best,
Kenan

On Monday, January 16, 2012 8:21:37 PM Imar Spaanjaars said:
Hi Kenan,

You can buy something from my Amazon wishlist: http://amzn.com/w/1I8QG3UOD16GU

If you forward me the order confirmation, I'll send you the 3.5 version right away (there's no PDF of the 2.0 version).

Cheers,

Imar
On Wednesday, February 29, 2012 10:22:51 AM VAMSHIKRISHNA said:
info was really so nice and expecting some more articles on the same ...
On Saturday, May 19, 2012 10:35:09 AM Ashutosh Dixit said:
Excellent Explanation. Keep up good work Thanks
On Tuesday, March 05, 2013 9:37:40 AM abdallah said:
hi Imar
I have used you template several times and i get the generated code but once it get it me an error Message: Object doesn't support this property or method and when clicked it go to this line
(For Each column in objTable.Columns) in all template.
Thanks
On Tuesday, March 05, 2013 2:11:16 PM Imar Spaanjaars said:
Hi there,

I have no idea what you're talking about, or which code you're referring to.

Sorry.

Imar
On Saturday, May 18, 2013 7:09:23 AM deepes said:
i dont know anything

Talk Back! Comment on Imar.Spaanjaars.Com

I am interested in what you have to say about this article. Feel free to post any comments, remarks or questions you may have about this article. The Talk Back feature is not meant for technical questions that are not directly related to this article. So, a post like "Hey, can you tell me how I can upload files to a MySQL database in PHP?" is likely to be removed. Also spam and unrealistic job offers will be deleted immediately.

When you post a comment, you have to provide your name and the comment. Your e-mail address is optional and you only need to provide it if you want me to contact you. It will not be displayed along with your comment. I got sick and tired of the comment spam I was receiving, so I have protected this page with a simple calculation exercise. This means that if you want to leave a comment, you'll need to complete the calculation before you hit the Post Comment button.

If you want to object to a comment made by another visitor, be sure to contact me and I'll look into it ASAP. Don't forget to mention the page link, or the QuickDocId of the document.

For more information about the Talk Back feature, check out this news item.