The Entity class(es)

A significant portion of my new Peter’s Business Logic Driven UI (“BLD”) module is in the Business Logic Layer (“BLL”). Having been a UI tools guy for a long time, I learned a lot about the BLL during this project. This article starts a series that digs into the BLL as I’ve implemented it for BLD.

These articles may apply to different audiences: novices, users looking to fix the flaws of their BLL, and certainly BLD users. Use the “Understanding the BLL” Category to see all articles.

Let’s get started on the concept of the Entity class.

The Entity class describes the structure of the table, where properties map to columns in the database. The properties are called DataFields throughout BLD.

There are actually three Entity class definitions for each table.

DAL Entity class

The Data Access Layer (“DAL”) defines the actual class that maps properties to columns. It is the purest form of the Entity class. The technologies behind the Data Access Layers each know how to generate these classes automatically. Those technologies include the ADO.NET Entity Framework, LINQ to SQL, nHibernate, LLBLGen Pro, and any other O/RM.

Here is a simplified version of the Category table from the Northwind database as generated by Entity Framework:

[C#]

[EdmEntityTypeAttribute(NamespaceName="NorthwindModel", Name="Category")]
public partial class Category : EntityObject
{
  [EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)]
  public System.Int32 CategoryID
  { … }
  [EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=false)]
  public System.String CategoryName
  { … }
  [EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=true)]
  public System.String Description
  { … }
}

[VB]

<EdmEntityTypeAttribute(NamespaceName:= "NorthwindModel", Name:="Category") >_
Public Partial Class Category 
  Inherits EntityObject
  <EdmScalarPropertyAttribute(EntityKeyProperty:=True, IsNullable:=False)>_
  Public Property CategoryID As System.Int32 
  End Property
  <EdmScalarPropertyAttribute(EntityKeyProperty:=False, IsNullable:=False)>_
  Public Property CategoryName As System.String 
  End Property
  <EdmScalarPropertyAttribute(EntityKeyProperty:=False, IsNullable:=True)>_
  Public Property Description As System.String 
  End Property
End Class

BLL Entity class

The Business Logic Layer defines a companion class where business rules associated with the Entity are defined. This class uses the same namespace and class name as the DAL Entity class. Both classes use the partial keyword to merge with each other. While it handles business rules, it cannot handle all of them. (That’s where the final Entity class comes in, as describe later.) BLL Entity handles custom properties (calculated fields for example) and any methods you need, such as custom validation code.

Here is the Category Entity class in the BLL with a custom property and validation method.

[C#]

using System.ComponentModel.DataAnnotations;
public partial class Category  
{
    public string ShortName
    {
        get 
        { 
            if (this.CategoryName.Length > 4)
                return this.CategoryName.SubString(0, 4); 
            else
                return this.CategoryName;
        }
    }
    public ValidationResult CheckForDuplicateCategoryNames(
      string newName, ValidationContext validationContext)
   {
        if (IsDuplicateName(newName)) // this code is left to the user
            return new ValidationResult("Duplicate name");
      return ValidationResult.Success;
   }
 
}

[VB]

Imports System.ComponentModel.DataAnnotations
Public Partial Class Category
    Public ReadOnly Property ShortName() As String
        Get
            If Me.CategoryName.Length > 4 Then
                Return Me.CategoryName.SubString(0, 4)
            Else
                Return Me.CategoryName
            End If
        End Get
    End Property
    Public Function CheckForDuplicateCategoryNames(newName As String, validationContext As ValidationContext) As ValidationResult
        If IsDuplicateName(newName) Then
            ' this code is left to the user
            Return New ValidationResult("Duplicate name")
        End If
        Return ValidationResult.Success
    End Function
 
End Class

Entity Metadata class

The third class hosts DataAnnotation attributes on the DataFields (properties of the DAL Entity class). DataAnnotation attributes are a significant tool in defining your business rules. Attributes apply metadata to properties and classes. DataAnnotation attributes are attribute classes describing business rules. We’ll cover various DataAnnotation attributes in detail later in this series.

The easiest approach for adding DataAnnotation attributes to properties is directly in the DAL Entity class because it already declares each property name. However, business rules belong in the BLL, not the DAL. So don’t do that!

The next natural place for this data is in the BLL Entity class, but .net is not quite up to the task because we want to attach the attributes to properties of the same name of the columns in our table. Those properties are defined in the DAL Entity. While we are using the partial keyword to merge BLL and DAL Entities, the partial keyword does not work on individual properties.

Microsoft solved this by defining the Entity Metadata class where you add properties with names matching the column names. It is connected to the BLL Entity class through the System.ComponentModel.DataAnnotations.MetadataTypeAttribute.

As you need to add DataAnnotation attributes to a property already defined in the DAL Entity, define a new property of the same name. This property is merely a placeholder for metadata, so its type and code are not used. This example shows how these properties are typically defined, with the type of Object (instead of the real type) and empty GET and SET clauses.

[C#]

[MetadataType(typeof(CategoryMetadata))]
public partial class Category  
{
    // see above
}
 
public class CategoryMetadata
{
    [Required()]
    [StringLength(30)]
   [CustomValidation(MethodName="CheckForDuplicateCategoryNames")]
   public object CategoryName { get; set; }
}

[VB]

<MetadataType(typeof(CategoryMetadata))> _
Public Partial Class Category
    ' see above
End Category
 
Public Class CategoryMetadata
    <Required()> _
    <StringLength(30)> _
  <CustomValidation(MethodName := "CheckForDuplicateCategoryNames")> _
  Public Property CategoryName As Object
    Get
      Return Nothing
    End Get
    Set
    End Set
  End Property
End Class

The Entity Metadata class is just one way to supply DataAnnotation attributes to BLD. As explained in the next topic, BLD defines the DataFieldDescriptor class to hold instances of all DataAnnotation attributes per field. The default DataFieldDescriptors know to look in the Entity Metadata class for this data. But you can also create your own system, such as a database or XML file that defines each business rule. BLD will call an event handler where you can create the list of DataAnnotation attributes from your resource.

No Comments