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.