<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://msmvps.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Deborah's Developer MindScape : Enum, OOP</title><link>http://msmvps.com/blogs/deborahk/archive/tags/Enum/OOP/default.aspx</link><description>Tags: Enum, OOP</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>Building a Business Object Base Class</title><link>http://msmvps.com/blogs/deborahk/archive/2009/07/21/building-a-business-object-base-class.aspx</link><pubDate>Tue, 21 Jul 2009 18:49:48 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1704681</guid><dc:creator>Deborah Kurata</dc:creator><slash:comments>16</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/deborahk/rsscomments.aspx?PostID=1704681</wfw:commentRss><comments>http://msmvps.com/blogs/deborahk/archive/2009/07/21/building-a-business-object-base-class.aspx#comments</comments><description>&lt;p&gt;If you are building applications in .NET to manage data for a business, you are most likely creating business object classes. Depending on the business, these classes could include Customer, Product, Order, Invoice, PurchaseOrder, Employee, TimeCard and so on.&lt;/p&gt;  &lt;p&gt;A simple sample Customer class is shown &lt;a href="http://msmvps.com/blogs/deborahk/archive/2009/07/03/generics-building-a-list-of-customers.aspx" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;There are some features that all business objects need to support. For example:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Entity State: The business object needs to track whether it is new, updated, or deleted so it can make the appropriate change to the database. &lt;/li&gt;    &lt;li&gt;Validation: Is the current data defined for the business object valid? &lt;/li&gt;    &lt;li&gt;Save: Saves the changes to the database. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Notice that data retrieval functionality is not included in this list. That is because in most cases, you may never retrieve a single business object. Rather, you would retrieve a set of them. For example, all active orders or all customers with overdue invoices. So the retrieve functionality is not included in the class that manages a single object. (Most on this in a later post.)&lt;/p&gt;  &lt;p&gt;Instead of repeating this common functionality in each business object, it makes sense to build a base class. Each business object can then inherit from this base class to share this common functionality.&lt;/p&gt;  &lt;p&gt;So let’s get started.&lt;/p&gt;  &lt;p&gt;In C#:&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;using System;      &lt;br /&gt;using System.ComponentModel;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;public abstract class BoBase :      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; IDataErrorInfo,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; INotifyPropertyChanged       &lt;br /&gt;{       &lt;br /&gt;      &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;In VB:&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;Imports System.ComponentModel      &lt;br /&gt;      &lt;br /&gt;Public MustInherit Class BOBase       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Implements IDataErrorInfo       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Implements INotifyPropertyChanged       &lt;br /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;End Class&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;The class is abstract (MustInherit in VB) to indicate that it is meant to be a base class and not to be used on its own. An abstract class cannot be instantiated directly, so no other code can create an instance of the class.&lt;/p&gt;  &lt;p&gt;The class then implements two interfaces:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;IDataErrorInfo: This interface provides error information that the user interface can use to report validation errors to the user. It works well with the ErrorProvider control provided in WinForms and supports ASP.NET and WPF features. &lt;/li&gt;    &lt;li&gt;INotifyPropertyChanged: This interface ensures that the user interface is notified when a property value changes, keeping your business object and user interface in sync. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;We’ll look at the implementation of these interfaces shortly.&lt;/p&gt;  &lt;p&gt;First, define the valid set of entity states.&lt;/p&gt;  &lt;p&gt;In C#:&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;protected internal enum EntityStateType      &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Unchanged,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Added,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Deleted,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Modified       &lt;br /&gt;}&lt;/font&gt; &lt;/p&gt;  &lt;p&gt;In VB:&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;Protected Friend Enum EntityStateType      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Unchanged       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Added       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Deleted       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Modified       &lt;br /&gt;End Enum&lt;/font&gt; &lt;/p&gt;  &lt;p&gt;The Enum is declared Protected because the entity state should only be accessible from the business object itself. However, Internal (Friend in VB) was added so that related objects (such as Order and OrderLineItem) could reference the related object state.&lt;/p&gt;  &lt;p&gt;The business object state is retained using an EntityState property.&lt;/p&gt;  &lt;p&gt;In C#:&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;protected EntityStateType EntityState { get; private set; }&lt;/font&gt; &lt;/p&gt;  &lt;p&gt;In VB:&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;Private _EntityState As EntityStateType      &lt;br /&gt;Protected Property EntityState() As EntityStateType       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Get       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Return _EntityState       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; End Get       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Private Set(ByVal value As EntityStateType)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; _EntityState = value       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; End Set       &lt;br /&gt;End Property&lt;/font&gt; &lt;/p&gt;  &lt;p&gt;This property is protected, but the setter is private. So the business objects that inherit from this class can read the entity state, but only the base class can set the value.&lt;/p&gt;  &lt;p&gt;Additional properties provide a way to get the entity’s state in an easier fashion. These properties are not required, but they make the base class a little easier to use.&lt;/p&gt;  &lt;p&gt;In C#:&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;[BindableAttribute(false)]      &lt;br /&gt;[BrowsableAttribute(false)]       &lt;br /&gt;public bool IsDirty       &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; get { return this.EntityState != EntityStateType.Unchanged; }       &lt;br /&gt;} &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;[BindableAttribute(false)]      &lt;br /&gt;[BrowsableAttribute(false)]       &lt;br /&gt;public bool IsNew       &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; get { return this.EntityState == EntityStateType.Added; }       &lt;br /&gt;}&lt;/font&gt; &lt;/p&gt;  &lt;p&gt;In VB:&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;&amp;lt;BindableAttribute(False)&amp;gt; _      &lt;br /&gt;&amp;lt;BrowsableAttribute(False)&amp;gt; _       &lt;br /&gt;Public ReadOnly Property IsDirty() As Boolean       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Get       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Return Me.EntityState &amp;lt;&amp;gt; EntityStateType.Unchanged       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; End Get       &lt;br /&gt;End Property &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;&amp;lt;BindableAttribute(False)&amp;gt; _      &lt;br /&gt;&lt;/font&gt;&lt;font color="#65402e" face="Consolas"&gt;&amp;lt;BrowsableAttribute(False)&amp;gt; _      &lt;br /&gt;Public ReadOnly Property IsNew() As Boolean       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Get       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Return Me.EntityState = EntityStateType.Added       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; End Get       &lt;br /&gt;End Property&lt;/font&gt; &lt;/p&gt;  &lt;p&gt;The IsDirty and IsNew properties are public, so they can be accessed from anywhere. They are marked with two attributes:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Bindable: Defines whether the property should be used for binding. In this case the value is false because the user interface should not be able to bind to this property. &lt;/li&gt;    &lt;li&gt;Browsable: Defines whether the property should be displayed in the Properties window. Again, the value is false. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Two other properties handle the validation.&lt;/p&gt;  &lt;p&gt;In C#:&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;[BindableAttribute(false)]      &lt;br /&gt;[BrowsableAttribute(false)]       &lt;br /&gt;public bool IsValid       &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; get { return (ValidationInstance.Count == 0); }       &lt;br /&gt;} &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;protected Validation ValidationInstance { get; set; }&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;In VB:&lt;/p&gt; &lt;font color="#65402e" face="Consolas"&gt;&amp;lt;Bindable(False)&amp;gt; _&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;lt;BrowsableAttribute(False)&amp;gt; _     &lt;br /&gt;Public ReadOnly Property IsValid() As Boolean     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Get     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Return (ValidationInstance.Count = 0)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; End Get     &lt;br /&gt;End Property &lt;/font&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;Private _ValidationInstance As Validation      &lt;br /&gt;Protected Property ValidationInstance() As Validation       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Get       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Return _ValidationInstance       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; End Get       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Private Set(ByVal value As Validation)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; _ValidationInstance = value       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; End Set       &lt;br /&gt;End Property&lt;/font&gt; &lt;/p&gt;  &lt;p&gt;Again, the public property is marked with the Browsable and Bindable attributes. The ValidationInstance property retains an instance of the Validation class for the business object. The code for the Validation class is &lt;a href="http://msmvps.com/blogs/deborahk/archive/2009/07/16/validation-class.aspx" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;The constructor creates an instance of the Validation class.&lt;/p&gt;  &lt;p&gt;In C#:&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;protected BoBase()      &lt;br /&gt;{&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160; ValidationInstance = new Validation();       &lt;br /&gt;}&lt;/font&gt; &lt;/p&gt;  &lt;p&gt;In VB:&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;Protected Sub New()     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ValidationInstance = New Validation      &lt;br /&gt;End Sub&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;The following is the implementation of IDataErrorInfo.&lt;/p&gt;  &lt;p&gt;In C#:&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;#region IDataErrorInfo Members &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;[BrowsableAttribute(false)]      &lt;br /&gt;[BindableAttribute(false)]       &lt;br /&gt;public string Error       &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; get { return ValidationInstance.ToString(); }       &lt;br /&gt;} &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;[BrowsableAttribute(false)]      &lt;br /&gt;[BindableAttribute(false)]       &lt;br /&gt;public string this[string columnName]       &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; get { return ValidationInstance[columnName]; }       &lt;br /&gt;} &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;#endregion&lt;/font&gt; &lt;/p&gt;  &lt;p&gt;In VB:&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;#Region &amp;quot; Properties required by the IDataErrorInfo&amp;quot;      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;Bindable(False)&amp;gt; _&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;BrowsableAttribute(False)&amp;gt; _       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Public ReadOnly Property [Error]() As String _       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Implements IDataErrorInfo.Error       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Get       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Return ValidationInstance.ToString       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; End Get       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; End Property &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;BrowsableAttribute(False)&amp;gt; _      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;Bindable(False)&amp;gt; _       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Default Protected ReadOnly Property Item(ByVal columnName _&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; As String) As String _&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Implements IDataErrorInfo.Item       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Get       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Return ValidationInstance.Item(columnName)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; End Get       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; End Property       &lt;br /&gt;      &lt;br /&gt;#End Region&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;The &lt;strong&gt;Error&lt;/strong&gt; property uses the overridden ToString method of the validation class to return the full list of validation errors.&lt;/p&gt;  &lt;p&gt;The &lt;strong&gt;Item&lt;/strong&gt; property provides access to the validation errors given a property name. This property is implemented as the class indexer in C#.&lt;/p&gt;  &lt;p&gt;The following in the implementation of INotifyPropertyChanged.&lt;/p&gt;  &lt;p&gt;In C#:&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;#region INotifyPropertyChanged Members     &lt;br /&gt;public event PropertyChangedEventHandler PropertyChanged;      &lt;br /&gt;#endregion&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;In VB:&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;#Region &amp;quot; Events required by INotifyPropertyChanged&amp;quot;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Public Event PropertyChanged(ByVal sender As Object, _      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ByVal e As System.ComponentModel.PropertyChangedEventArgs) _      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Implements INotifyPropertyChanged.PropertyChanged      &lt;br /&gt;#End Region&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;This interface only defines a single event. This event should be raised whenever the data is changed.&lt;/p&gt;  &lt;p&gt;Since every business object will have unique requirements for the save operation, the &lt;strong&gt;SaveItem&lt;/strong&gt; method is not implemented. Rather it is defined as abstract.&lt;/p&gt;  &lt;p&gt;In C#:&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;public abstract Boolean SaveItem();&lt;/font&gt; &lt;/p&gt;  &lt;p&gt;In VB:&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;Public MustOverride Function SaveItem() As Boolean&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Defining an abstract (MustOverride in VB) SaveItem method ensures that every business object has a SaveItem method.&lt;/p&gt;  &lt;p&gt;Finally, since the EntityState property setter is private, the base class needs a method to set the entity state.&lt;/p&gt;  &lt;p&gt;In C#:&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;protected internal void SetEntityState(EntityStateType newEntityState)     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; switch (newEntityState)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case EntityStateType.Deleted:      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case EntityStateType.Unchanged:      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case EntityStateType.Added:      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.EntityState = newEntityState;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; break; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;&amp;#160;&amp;#160;&amp;#160; default:     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (this.EntityState == EntityStateType.Unchanged)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.EntityState = newEntityState;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; break;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;protected internal void SetEntityState(EntityStateType newEntityState, string propertyName)     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; SetEntityState(newEntityState);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (PropertyChanged != null)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; PropertyChanged(this,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;font color="#65402e" face="Consolas"&gt;new PropertyChangedEventArgs(propertyName));     &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;In VB:&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;Protected Friend Sub SetEntityState(ByVal dataState As EntityStateType)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; SetEntityState(dataState, Nothing)      &lt;br /&gt;End Sub &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;Protected Friend Sub SetEntityState( _     &lt;br /&gt; ByVal newEntityState As EntityStateType, ByVal propertyName As String)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Select Case newEntityState      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Case EntityStateType.Deleted, _      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; EntityStateType.Unchanged, _      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; EntityStateType.Added      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Me.EntityState = newEntityState &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Case Else     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; If Me.EntityState = EntityStateType.Unchanged Then      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Me.EntityState = newEntityState      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; End If      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; End Select &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;&amp;#160;&amp;#160;&amp;#160; If Not String.IsNullOrEmpty(propertyName) Then     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Dim e As New PropertyChangedEventArgs(propertyName)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; RaiseEvent PropertyChanged(Me, e)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; End If      &lt;br /&gt;End Sub&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;The &lt;strong&gt;SetEntityState&lt;/strong&gt; method has two overloads. The first is used when changing the entity state in general and the second is used when changing the entity state because a specific property is changed.&lt;/p&gt;  &lt;p&gt;For example, when setting an object as Unchanged, Added, or Deleted, it does not matter which property was changed. But when a particular property is changed, the code must also raise the PropertyChanged event.&lt;/p&gt;  &lt;p&gt;In this case, the C# and VB code was implemented differently. In the C# code, the code to set the entity state is in the first overload. The second overload then calls the first and then raises the event.&lt;/p&gt;  &lt;p&gt;In the VB code, the first overload simply calls the second overload. The second overload then sets the entity state and then raises the event as appropriate. You can use either technique in either language.&lt;/p&gt;  &lt;p&gt;That’s it! You now have a base class that can be used with any business object class. If you have any other common functionality, you can add it to this base class. &lt;/p&gt;  &lt;p&gt;Here is an example of how you use this base class.&lt;/p&gt;  &lt;p&gt;In C#:&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;public class Customer : BoBase     &lt;br /&gt;{      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; private string _LastName;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public string LastName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; get { return _LastName; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; set      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (_LastName == null || _LastName != value)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; string propertyName = &amp;quot;LastName&amp;quot;;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; _LastName = value; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // Validate the last name     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ValidationInstance.ValidateClear(propertyName);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ValidationInstance.ValidateRequired(propertyName, value); &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; SetEntityState(EntityStateType.Modified, propertyName);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;&amp;#160;&amp;#160;&amp;#160; public override Boolean SaveItem()     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // TODO: Add code here      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;In VB:&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;Public Class Customer     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Inherits BoBase&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;&amp;#160;&amp;#160;&amp;#160; Private _LastName As String     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Public Property LastName() As String      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Get      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Return _LastName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; End Get      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Set(ByVal value As String)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; If _LastName Is Nothing OrElse _LastName &amp;lt;&amp;gt; value Then      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Dim propertyName As String = &amp;quot;LastName&amp;quot;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; _LastName = value &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;#39; Validate the last name     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ValidationInstance.ValidateClear(propertyName)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ValidationInstance.ValidateRequired(propertyName, value) &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; SetEntityState(EntityStateType.Modified, propertyName)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; End If      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; End Set      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; End Property&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#65402e" face="Consolas"&gt;&amp;#160;&amp;#160;&amp;#160; Public Overrides Function SaveItem() As Boolean     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;#39; TODO: Add code here      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; End Function      &lt;br /&gt;End Class&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Notice how the class statement includes the syntax to inherit from BoBase. The LastName property uses the ValidationInstance defined in the base class to validate the value. It also sets the entity state when the last name is changed.&lt;/p&gt;  &lt;p&gt;Enjoy!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1704681" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/deborahk/archive/tags/VB/default.aspx">VB</category><category domain="http://msmvps.com/blogs/deborahk/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://msmvps.com/blogs/deborahk/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/deborahk/archive/tags/CSharp/default.aspx">CSharp</category><category domain="http://msmvps.com/blogs/deborahk/archive/tags/OOP/default.aspx">OOP</category><category domain="http://msmvps.com/blogs/deborahk/archive/tags/Enum/default.aspx">Enum</category><category domain="http://msmvps.com/blogs/deborahk/archive/tags/Binding/default.aspx">Binding</category></item></channel></rss>