838 lines
30 KiB
VB.net
838 lines
30 KiB
VB.net
Imports System.IO
|
|
Imports System.Reflection
|
|
Imports System.Runtime.Serialization.Formatters.Binary
|
|
Imports System.ComponentModel
|
|
Imports System.Configuration
|
|
|
|
''AyaNova Imports
|
|
Imports System.Threading
|
|
Imports CSLA.Security
|
|
|
|
''' <summary>
|
|
''' This is the base class from which most business objects
|
|
''' will be derived.
|
|
''' </summary>
|
|
''' <remarks>
|
|
''' <para>
|
|
''' This class is the core of the CSLA .NET framework. To create
|
|
''' a business object, inherit from this class.
|
|
''' </para><para>
|
|
''' Please refer to 'Expert One-on-One VB.NET Business Objects' for
|
|
''' full details on the use of this base class to create business
|
|
''' objects.
|
|
''' </para>
|
|
''' </remarks>
|
|
<Serializable()> _
|
|
Public MustInherit Class BusinessBase
|
|
Inherits Core.UndoableBase
|
|
|
|
Implements IEditableObject
|
|
Implements ICloneable
|
|
Implements IDataErrorInfo
|
|
Implements Serialization.ISerializationNotification
|
|
|
|
#Region "AyaNova related convenience items"
|
|
''Get the user object so
|
|
''we can check rights / get ID value
|
|
<Browsable(False)> _
|
|
Public ReadOnly Property CurrentUserID() As Guid
|
|
Get
|
|
Dim CurrentUser As Security.BusinessPrincipal = CType(Thread.CurrentPrincipal, BusinessPrincipal)
|
|
|
|
Return CurrentUser.ID
|
|
|
|
End Get
|
|
End Property
|
|
|
|
|
|
''Confirm if notification is on or off from current principle object
|
|
<Browsable(False)> _
|
|
Public ReadOnly Property Notify() As Boolean
|
|
Get
|
|
Dim CurrentUser As Security.BusinessPrincipal = CType(Thread.CurrentPrincipal, BusinessPrincipal)
|
|
|
|
Return CurrentUser.UseNotification
|
|
|
|
End Get
|
|
End Property
|
|
|
|
'' Get security access right level from current identity
|
|
Public Function GetRight(ByVal RightName As String) As Int32
|
|
Return CType(Thread.CurrentPrincipal, BusinessPrincipal).Right(RightName)
|
|
End Function
|
|
|
|
|
|
''Added to give UI ability to know if object is in an
|
|
''edit level greater than zero
|
|
<Browsable(False)> _
|
|
Public ReadOnly Property IsEditing() As Boolean
|
|
Get
|
|
Return (EditLevel > 0)
|
|
End Get
|
|
End Property
|
|
|
|
|
|
#End Region
|
|
|
|
#Region " IsNew, IsDeleted, IsDirty "
|
|
|
|
' keep track of whether we are new, deleted or dirty
|
|
Private mIsNew As Boolean = True
|
|
Private mIsDeleted As Boolean = False
|
|
Private mIsDirty As Boolean = True
|
|
|
|
''' <summary>
|
|
''' Returns True if this is a new object, False if it is a pre-existing object.
|
|
''' </summary>
|
|
''' <remarks>
|
|
''' An object is considered to be new if its data doesn't correspond to
|
|
''' data in the database. In other words, if the data values in this particular
|
|
''' object have not yet been saved to the database the object is considered to
|
|
''' be new. Likewise, if the object's data has been deleted from the database
|
|
''' then the object is considered to be new.
|
|
''' </remarks>
|
|
''' <returns>A value indicating if this object is new.</returns>
|
|
<Browsable(False)> _
|
|
Public ReadOnly Property IsNew() As Boolean
|
|
Get
|
|
Return mIsNew
|
|
End Get
|
|
End Property
|
|
|
|
''' <summary>
|
|
''' Returns True if this object is marked for deletion.
|
|
''' </summary>
|
|
''' <remarks>
|
|
''' CSLA .NET supports both immediate and deferred deletion of objects. This
|
|
''' property is part of the support for deferred deletion, where an object
|
|
''' can be marked for deletion, but isn't actually deleted until the object
|
|
''' is saved to the database. This property indicates whether or not the
|
|
''' current object has been marked for deletion. If it is True, the object will
|
|
''' be deleted when it is saved to the database, otherwise it will be inserted
|
|
''' or updated by the save operation.
|
|
''' </remarks>
|
|
''' <returns>A value indicating if this object is marked for deletion.</returns>
|
|
<Browsable(False)> _
|
|
Public ReadOnly Property IsDeleted() As Boolean
|
|
Get
|
|
Return mIsDeleted
|
|
End Get
|
|
End Property
|
|
|
|
''' <summary>
|
|
''' Returns True if this object's data has been changed.
|
|
''' </summary>
|
|
''' <remarks>
|
|
''' <para>
|
|
''' When an object's data is changed, CSLA .NET makes note of that change
|
|
''' and considers the object to be 'dirty' or changed. This value is used to
|
|
''' optimize data updates, since an unchanged object does not need to be
|
|
''' updated into the database. All new objects are considered dirty. All objects
|
|
''' marked for deletion are considered dirty.
|
|
''' </para><para>
|
|
''' Once an object's data has been saved to the database (inserted or updated)
|
|
''' the dirty flag is cleared and the object is considered unchanged. Objects
|
|
''' newly loaded from the database are also considered unchanged.
|
|
''' </para>
|
|
''' </remarks>
|
|
''' <returns>A value indicating if this object's data has been changed.</returns>
|
|
<Browsable(False)> _
|
|
Public Overridable ReadOnly Property IsDirty() As Boolean
|
|
Get
|
|
Return mIsDirty
|
|
End Get
|
|
End Property
|
|
|
|
''' <summary>
|
|
''' Marks the object as being a new object. This also marks the object
|
|
''' as being dirty and ensures that it is not marked for deletion.
|
|
''' </summary>
|
|
''' <remarks>
|
|
''' Newly created objects are marked new by default. You should call
|
|
''' this method in the implementation of DataPortal_Update when the
|
|
''' object is deleted (due to being marked for deletion) to indicate
|
|
''' that the object no longer reflects data in the database.
|
|
''' </remarks>
|
|
Protected Sub MarkNew()
|
|
mIsNew = True
|
|
mIsDeleted = False
|
|
MarkDirty()
|
|
End Sub
|
|
|
|
''' <summary>
|
|
''' Marks the object as being an old (not new) object. This also
|
|
''' marks the object as being unchanged (not dirty).
|
|
''' </summary>
|
|
''' <remarks>
|
|
''' <para>
|
|
''' You should call this method in the implementation of
|
|
''' DataPortal_Fetch to indicate that an existing object has been
|
|
''' successfully retrieved from the database.
|
|
''' </para><para>
|
|
''' You should call this method in the implementation of
|
|
''' DataPortal_Update to indicate that a new object has been successfully
|
|
''' inserted into the database.
|
|
''' </para>
|
|
''' </remarks>
|
|
Protected Sub MarkOld()
|
|
mIsNew = False
|
|
MarkClean()
|
|
End Sub
|
|
|
|
''' <summary>
|
|
''' Marks an object for deletion. This also marks the object
|
|
''' as being dirty.
|
|
''' </summary>
|
|
''' <remarks>
|
|
''' You should call this method in your business logic in the
|
|
''' case that you want to have the object deleted when it is
|
|
''' saved to the database.
|
|
''' </remarks>
|
|
Protected Sub MarkDeleted()
|
|
mIsDeleted = True
|
|
MarkDirty()
|
|
End Sub
|
|
|
|
''' <summary>
|
|
''' Marks an object as being dirty, or changed.
|
|
''' </summary>
|
|
''' <remarks>
|
|
''' <para>
|
|
''' You should call this method in your business logic any time
|
|
''' the object's internal data changes. Any time any instance
|
|
''' variable changes within the object, this method should be called
|
|
''' to tell CSLA .NET that the object's data has been changed.
|
|
''' </para><para>
|
|
''' Marking an object as dirty does two things. First it ensures
|
|
''' that CSLA .NET will properly save the object as appropriate. Second,
|
|
''' it causes CSLA .NET to tell Windows Forms data binding that the
|
|
''' object's data has changed so any bound controls will update to
|
|
''' reflect the new values.
|
|
''' </para>
|
|
''' </remarks>
|
|
Protected Sub MarkDirty()
|
|
mIsDirty = True
|
|
OnIsDirtyChanged()
|
|
End Sub
|
|
|
|
Private Sub MarkClean()
|
|
mIsDirty = False
|
|
OnIsDirtyChanged()
|
|
End Sub
|
|
|
|
#End Region
|
|
|
|
#Region " IsSavable "
|
|
|
|
''' <summary>
|
|
''' Returns True if this object is both dirty and valid.
|
|
''' </summary>
|
|
''' <remarks>
|
|
''' An object is considered dirty (changed) if
|
|
''' <see cref="P:CSLA.BusinessBase.IsDirty" /> returns True. It is
|
|
''' considered valid if <see cref="P:CSLA.BusinessBase.IsValid" />
|
|
''' returns True. The IsSavable property is
|
|
''' a combination of these two properties. It is provided specifically to
|
|
''' enable easy binding to a Save or OK button on a form so that button
|
|
''' can automatically enable/disable as the object's state changes between
|
|
''' being savable and not savable.
|
|
''' </remarks>
|
|
''' <returns>A value indicating if this object is new.</returns>
|
|
<Browsable(False)> _
|
|
Public Overridable ReadOnly Property IsSavable() As Boolean
|
|
Get
|
|
Return IsDirty AndAlso IsValid
|
|
End Get
|
|
End Property
|
|
|
|
#End Region
|
|
|
|
#Region " IEditableObject "
|
|
|
|
<NotUndoable()> _
|
|
Private mParent As BusinessCollectionBase
|
|
<NotUndoable()> _
|
|
Private mBindingEdit As Boolean = False
|
|
Private mNeverCommitted As Boolean = True
|
|
|
|
''' <summary>
|
|
''' Used by <see cref="T:CSLA.BusinessCollectionBase" /> as a
|
|
''' child object is created to tell the child object about its
|
|
''' parent.
|
|
''' </summary>
|
|
''' <param name="parent">A reference to the parent collection object.</param>
|
|
Friend Sub SetParent(ByVal parent As BusinessCollectionBase)
|
|
|
|
If Not IsChild Then
|
|
Throw New Exception("Parent value can only be set for child objects")
|
|
End If
|
|
mParent = parent
|
|
|
|
End Sub
|
|
|
|
''' <summary>
|
|
''' Allow data binding to start a nested edit on the object.
|
|
''' </summary>
|
|
''' <remarks>
|
|
''' Data binding may call this method many times. Only the first
|
|
''' call should be honored, so we have extra code to detect this
|
|
''' and do nothing for subsquent calls.
|
|
''' </remarks>
|
|
Private Sub IEditableObject_BeginEdit() Implements IEditableObject.BeginEdit
|
|
|
|
Debug.WriteLine("beginedit " & Me.ToString)
|
|
If Not mBindingEdit Then
|
|
BeginEdit()
|
|
End If
|
|
|
|
End Sub
|
|
|
|
''' <summary>
|
|
''' Allow data binding to cancel the current edit.
|
|
''' </summary>
|
|
''' <remarks>
|
|
''' Data binding may call this method many times. Only the first
|
|
''' call to either IEditableObject.CancelEdit or
|
|
''' <see cref="M:CSLA.BusinessBase.IEditableObject_EndEdit">IEditableObject.EndEdit</see>
|
|
''' should be honored. We include extra code to detect this and do
|
|
''' nothing for subsequent calls.
|
|
''' </remarks>
|
|
Private Sub IEditableObject_CancelEdit() Implements IEditableObject.CancelEdit
|
|
|
|
Debug.WriteLine("canceledit " & Me.ToString)
|
|
If mBindingEdit Then
|
|
CancelEdit()
|
|
If IsNew AndAlso mNeverCommitted AndAlso EditLevel <= EditLevelAdded Then
|
|
' we're new and no EndEdit or ApplyEdit has ever been
|
|
' called on us, and now we've been canceled back to
|
|
' where we were added so we should have ourselves
|
|
' removed from the parent collection
|
|
If Not mParent Is Nothing Then
|
|
mParent.RemoveChild(Me)
|
|
End If
|
|
End If
|
|
End If
|
|
|
|
End Sub
|
|
|
|
''' <summary>
|
|
''' Allow data binding to apply the current edit.
|
|
''' </summary>
|
|
''' <remarks>
|
|
''' Data binding may call this method many times. Only the first
|
|
''' call to either IEditableObject.EndEdit or
|
|
''' <see cref="M:CSLA.BusinessBase.IEditableObject_CancelEdit">IEditableObject.CancelEdit</see>
|
|
''' should be honored. We include extra code to detect this and do
|
|
''' nothing for subsequent calls.
|
|
''' </remarks>
|
|
Private Sub IEditableObject_EndEdit() Implements IEditableObject.EndEdit
|
|
|
|
Debug.WriteLine("endedit " & Me.ToString)
|
|
If mBindingEdit Then
|
|
ApplyEdit()
|
|
End If
|
|
|
|
End Sub
|
|
|
|
#End Region
|
|
|
|
#Region " Begin/Cancel/ApplyEdit "
|
|
|
|
''' <summary>
|
|
''' Starts a nested edit on the object.
|
|
''' </summary>
|
|
''' <remarks>
|
|
''' <para>
|
|
''' When this method is called the object takes a snapshot of
|
|
''' its current state (the values of its variables). This snapshot
|
|
''' can be restored by calling <see cref="M:CSLA.BusinessBase.CancelEdit" />
|
|
''' or committed by calling <see cref="M:CSLA.BusinessBase.ApplyEdit" />.
|
|
''' </para><para>
|
|
''' This is a nested operation. Each call to BeginEdit adds a new
|
|
''' snapshot of the object's state to a stack. You should ensure that
|
|
''' for each call to BeginEdit there is a corresponding call to either
|
|
''' CancelEdit or ApplyEdit to remove that snapshot from the stack.
|
|
''' </para><para>
|
|
''' See Chapters 2 and 4 for details on n-level undo and state stacking.
|
|
''' </para>
|
|
''' </remarks>
|
|
Public Sub BeginEdit()
|
|
mBindingEdit = True
|
|
CopyState()
|
|
End Sub
|
|
|
|
''' <summary>
|
|
''' Cancels the current edit process, restoring the object's state to
|
|
''' its previous values.
|
|
''' </summary>
|
|
''' <remarks>
|
|
''' Calling this method causes the most recently taken snapshot of the
|
|
''' object's state to be restored. This resets the object's values
|
|
''' to the point of the last <see cref="M:CSLA.BusinessBase.BeginEdit" />
|
|
''' call.
|
|
''' </remarks>
|
|
Public Sub CancelEdit()
|
|
mBindingEdit = False
|
|
UndoChanges()
|
|
OnIsDirtyChanged()
|
|
End Sub
|
|
|
|
''' <summary>
|
|
''' Commits the current edit process.
|
|
''' </summary>
|
|
''' <remarks>
|
|
''' Calling this method causes the most recently taken snapshot of the
|
|
''' object's state to be discarded, thus committing any changes made
|
|
''' to the object's state since the last <see cref="M:CSLA.BusinessBase.BeginEdit" />
|
|
''' call.
|
|
''' </remarks>
|
|
Public Sub ApplyEdit()
|
|
mBindingEdit = False
|
|
mNeverCommitted = False
|
|
AcceptChanges()
|
|
End Sub
|
|
|
|
#End Region
|
|
|
|
#Region " IsChild "
|
|
|
|
<NotUndoable()> _
|
|
Private mIsChild As Boolean = False
|
|
|
|
Friend ReadOnly Property IsChild() As Boolean
|
|
Get
|
|
Return mIsChild
|
|
End Get
|
|
End Property
|
|
|
|
''' <summary>
|
|
''' Marks the object as being a child object.
|
|
''' </summary>
|
|
''' <remarks>
|
|
''' <para>
|
|
''' By default all business objects are 'parent' objects. This means
|
|
''' that they can be directly retrieved and updated into the database.
|
|
''' </para><para>
|
|
''' We often also need child objects. These are objects which are contained
|
|
''' within other objects. For instance, a parent Invoice object will contain
|
|
''' child LineItem objects.
|
|
''' </para><para>
|
|
''' To create a child object, the MarkAsChild method must be called as the
|
|
''' object is created. Please see Chapter 7 for details on the use of the
|
|
''' MarkAsChild method.
|
|
''' </para>
|
|
''' </remarks>
|
|
Protected Sub MarkAsChild()
|
|
mIsChild = True
|
|
End Sub
|
|
|
|
#End Region
|
|
|
|
#Region " Delete "
|
|
|
|
''' <summary>
|
|
''' Marks the object for deletion. The object will be deleted as part of the
|
|
''' next save operation.
|
|
''' </summary>
|
|
''' <remarks>
|
|
''' <para>
|
|
''' CSLA .NET supports both immediate and deferred deletion of objects. This
|
|
''' method is part of the support for deferred deletion, where an object
|
|
''' can be marked for deletion, but isn't actually deleted until the object
|
|
''' is saved to the database. This method is called by the UI developer to
|
|
''' mark the object for deletion.
|
|
''' </para><para>
|
|
''' To 'undelete' an object, use <see cref="M:CSLA.BusinessBase.BeginEdit" /> before
|
|
''' calling the Delete method. You can then use <see cref="M:CSLA.BusinessBase.CancelEdit" />
|
|
''' later to reset the object's state to its original values. This will include resetting
|
|
''' the deleted flag to False.
|
|
''' </para>
|
|
''' </remarks>
|
|
Public Sub Delete()
|
|
If Me.IsChild Then
|
|
Throw New NotSupportedException("Can not directly mark a child object for deletion - use its parent collection")
|
|
End If
|
|
|
|
MarkDeleted()
|
|
|
|
End Sub
|
|
|
|
' allow the parent object to delete us
|
|
' (Friend scope)
|
|
Friend Sub DeleteChild()
|
|
If Not Me.IsChild Then
|
|
Throw New NotSupportedException("Invalid for root objects - use Delete instead")
|
|
End If
|
|
|
|
MarkDeleted()
|
|
|
|
End Sub
|
|
|
|
#End Region
|
|
|
|
#Region " Edit Level Tracking (child only) "
|
|
|
|
' we need to keep track of the edit
|
|
' level when we were added so if the user
|
|
' cancels below that level we can be destroyed
|
|
Private mEditLevelAdded As Integer
|
|
|
|
' allow the collection object to use the
|
|
' edit level as needed (Friend scope)
|
|
Friend Property EditLevelAdded() As Integer
|
|
Get
|
|
Return mEditLevelAdded
|
|
End Get
|
|
Set(ByVal Value As Integer)
|
|
mEditLevelAdded = Value
|
|
End Set
|
|
End Property
|
|
|
|
#End Region
|
|
|
|
#Region " Clone "
|
|
|
|
''' <summary>
|
|
''' Creates a clone of the object.
|
|
''' </summary>
|
|
''' <returns>A new object containing the exact data of the original object.</returns>
|
|
Public Function Clone() As Object _
|
|
Implements ICloneable.Clone
|
|
|
|
Dim buffer As New MemoryStream
|
|
Dim formatter As New BinaryFormatter
|
|
|
|
Serialization.SerializationNotification.OnSerializing(Me)
|
|
formatter.Serialize(buffer, Me)
|
|
Serialization.SerializationNotification.OnSerialized(Me)
|
|
buffer.Position = 0
|
|
Dim temp As Object = formatter.Deserialize(buffer)
|
|
Serialization.SerializationNotification.OnDeserialized(temp)
|
|
Return temp
|
|
|
|
End Function
|
|
|
|
#End Region
|
|
|
|
#Region " BrokenRules, IsValid "
|
|
|
|
' keep a list of broken rules
|
|
Private mBrokenRules As New BrokenRules
|
|
|
|
''' <summary>
|
|
''' Override this method in your business class to
|
|
''' be notified when you need to set up business
|
|
''' rules.
|
|
''' </summary>
|
|
''' <remarks>
|
|
''' You should call AddBusinessRules from your object's
|
|
''' constructor methods so the rules are set up when
|
|
''' your object is created. This method will be automatically
|
|
''' called, if needed, when your object is serialized by
|
|
''' the DataPortal or by the Clone method.
|
|
''' </remarks>
|
|
Protected Overridable Sub AddBusinessRules()
|
|
|
|
End Sub
|
|
|
|
''' <summary>
|
|
''' Returns True if the object is currently valid, False if the
|
|
''' object has broken rules or is otherwise invalid.
|
|
''' </summary>
|
|
''' <remarks>
|
|
''' <para>
|
|
''' By default this property relies on the underling <see cref="T:CSLA.BrokenRules" />
|
|
''' object to track whether any business rules are currently broken for this object.
|
|
''' </para><para>
|
|
''' You can override this property to provide more sophisticated
|
|
''' implementations of the behavior. For instance, you should always override
|
|
''' this method if your object has child objects, since the validity of this object
|
|
''' is affected by the validity of all child objects.
|
|
''' </para>
|
|
''' </remarks>
|
|
''' <returns>A value indicating if the object is currently valid.</returns>
|
|
<Browsable(False)> _
|
|
Public Overridable ReadOnly Property IsValid() As Boolean
|
|
Get
|
|
Return mBrokenRules.IsValid
|
|
End Get
|
|
End Property
|
|
|
|
''' <summary>
|
|
''' Provides access to the readonly collection of broken business rules
|
|
''' for this object.
|
|
''' </summary>
|
|
''' <returns>A <see cref="T:CSLA.BrokenRules.RulesCollection" /> object.</returns>
|
|
Public Overridable Function GetBrokenRulesCollection() As BrokenRules.RulesCollection
|
|
Return mBrokenRules.GetBrokenRules
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Provides access to a text representation of all the descriptions of
|
|
''' the currently broken business rules for this object.
|
|
''' </summary>
|
|
''' <returns>Text containing the descriptions of the broken business rules.</returns>
|
|
Public Overridable Function GetBrokenRulesString() As String
|
|
Return mBrokenRules.ToString
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Provides access to the broken rules functionality.
|
|
''' </summary>
|
|
''' <remarks>
|
|
''' This property is used within your business logic so you can
|
|
''' easily call the <see cref="M:CSLA.BrokenRules.Assert(System.String,System.String,System.Boolean)" />
|
|
''' method to mark rules as broken and unbroken.
|
|
''' </remarks>
|
|
Protected ReadOnly Property BrokenRules() As BrokenRules
|
|
Get
|
|
Return mBrokenRules
|
|
End Get
|
|
End Property
|
|
|
|
''' <summary>
|
|
''' Provides access to the broken rules as a single string
|
|
''' </summary>
|
|
''' <remarks>
|
|
''' AyaNova - Provides access to a single string containing broken rules text
|
|
''' for easier binding to single text display rather than lists as in default
|
|
''' implementation
|
|
''' </remarks>
|
|
<Browsable(False)> _
|
|
Public ReadOnly Property BrokenRulesText() As String
|
|
Get
|
|
Return mBrokenRules.ToString()
|
|
End Get
|
|
End Property
|
|
|
|
|
|
#End Region
|
|
|
|
#Region " Data Access "
|
|
|
|
''' <summary>
|
|
''' Saves the object to the database.
|
|
''' </summary>
|
|
''' <remarks>
|
|
''' <para>
|
|
''' Calling this method starts the save operation, causing the object
|
|
''' to be inserted, updated or deleted within the database based on the
|
|
''' object's current state.
|
|
''' </para><para>
|
|
''' If <see cref="P:CSLA.BusinessBase.IsDeleted" /> is True the object
|
|
''' will be deleted. Otherwise, if <see cref="P:CSLA.BusinessBase.IsNew" />
|
|
''' is True the object will be inserted. Otherwise the object's data will
|
|
''' be updated in the database.
|
|
''' </para><para>
|
|
''' All this is contingent on <see cref="P:CSLA.BusinessBase.IsDirty" />. If
|
|
''' this value is False, no data operation occurs. It is also contingent on
|
|
''' <see cref="P:CSLA.BusinessBase.IsValid" />. If this value is False an
|
|
''' exception will be thrown to indicate that the UI attempted to save an
|
|
''' invalid object.
|
|
''' </para><para>
|
|
''' It is important to note that this method returns a new version of the
|
|
''' business object that contains any data updated during the save operation.
|
|
''' You MUST update all object references to use this new version of the
|
|
''' business object in order to have access to the correct object data.
|
|
''' </para><para>
|
|
''' You can override this method to add your own custom behaviors to the save
|
|
''' operation. For instance, you may add some security checks to make sure
|
|
''' the user can save the object. If all security checks pass, you would then
|
|
''' invoke the base Save method via <c>MyBase.Save()</c>.
|
|
''' </para>
|
|
''' </remarks>
|
|
''' <returns>A new object containing the saved values.</returns>
|
|
Public Overridable Function Save() As BusinessBase
|
|
If Me.IsChild Then
|
|
Throw New NotSupportedException("Can not directly save a child object")
|
|
End If
|
|
|
|
If EditLevel > 0 Then
|
|
Throw New ApplicationException("Object is still being edited and can not be saved")
|
|
End If
|
|
|
|
If Not IsValid Then
|
|
Throw New ValidationException("Object is not valid and can not be saved")
|
|
End If
|
|
|
|
If IsDirty Then
|
|
Return CType(DataPortal.Update(Me), BusinessBase)
|
|
Else
|
|
Return Me
|
|
End If
|
|
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Override this method to load a new business object with default
|
|
''' values from the database.
|
|
''' </summary>
|
|
''' <param name="Criteria">An object containing criteria values.</param>
|
|
Protected Overridable Sub DataPortal_Create(ByVal Criteria As Object)
|
|
Throw New NotSupportedException("Invalid operation - create not allowed")
|
|
End Sub
|
|
|
|
''' <summary>
|
|
''' Override this method to allow retrieval of an existing business
|
|
''' object based on data in the database.
|
|
''' </summary>
|
|
''' <param name="Criteria">An object containing criteria values to identify the object.</param>
|
|
Protected Overridable Sub DataPortal_Fetch(ByVal Criteria As Object)
|
|
Throw New NotSupportedException("Invalid operation - fetch not allowed")
|
|
End Sub
|
|
|
|
''' <summary>
|
|
''' Override this method to allow insert, update or deletion of a business
|
|
''' object.
|
|
''' </summary>
|
|
Protected Overridable Sub DataPortal_Update()
|
|
Throw New NotSupportedException("Invalid operation - update not allowed")
|
|
End Sub
|
|
|
|
''' <summary>
|
|
''' Override this method to allow immediate deletion of a business object.
|
|
''' </summary>
|
|
''' <param name="Criteria">An object containing criteria values to identify the object.</param>
|
|
Protected Overridable Sub DataPortal_Delete(ByVal Criteria As Object)
|
|
Throw New NotSupportedException("Invalid operation - delete not allowed")
|
|
End Sub
|
|
|
|
''' <summary>
|
|
''' Returns the specified database connection string from the application
|
|
''' configuration file.
|
|
''' </summary>
|
|
''' <remarks>
|
|
''' The database connection string must be in the <c>appSettings</c> section
|
|
''' of the application configuration file. The database name should be
|
|
''' prefixed with 'DB:'. For instance, <c>DB:mydatabase</c>.
|
|
''' </remarks>
|
|
''' <param name="DatabaseName">Name of the database.</param>
|
|
''' <returns>A database connection string.</returns>
|
|
Protected Function DB(ByVal DatabaseName As String) As String
|
|
Return System.Configuration.ConfigurationManager.AppSettings("DB:" & DatabaseName)
|
|
End Function
|
|
|
|
#End Region
|
|
|
|
#Region " IDataErrorInfo "
|
|
|
|
Private ReadOnly Property [Error]() As String Implements System.ComponentModel.IDataErrorInfo.Error
|
|
Get
|
|
If Not IsValid Then
|
|
If BrokenRules.GetBrokenRules.Count = 1 Then
|
|
Return BrokenRules.GetBrokenRules.Item(0).Description
|
|
|
|
Else
|
|
Return BrokenRules.ToString
|
|
End If
|
|
End If
|
|
End Get
|
|
End Property
|
|
|
|
Private ReadOnly Property Item(ByVal columnName As String) As String Implements System.ComponentModel.IDataErrorInfo.Item
|
|
Get
|
|
If Not IsValid Then
|
|
Return BrokenRules.GetBrokenRules.RuleForProperty(columnName).Description
|
|
End If
|
|
End Get
|
|
End Property
|
|
|
|
#End Region
|
|
|
|
#Region " ISerializationNotification "
|
|
|
|
''' <summary>
|
|
''' This method is called on a newly deserialized object
|
|
''' after deserialization is complete.
|
|
''' </summary>
|
|
Protected Overridable Sub Deserialized() _
|
|
Implements CSLA.Serialization.ISerializationNotification.Deserialized
|
|
|
|
AddBusinessRules()
|
|
|
|
' now cascade the call to all child objects/collections
|
|
Dim fields() As FieldInfo
|
|
Dim field As FieldInfo
|
|
|
|
' get the list of fields in this type
|
|
fields = Me.GetType.GetFields( _
|
|
BindingFlags.NonPublic Or _
|
|
BindingFlags.Instance Or _
|
|
BindingFlags.Public)
|
|
|
|
For Each field In fields
|
|
If Not field.FieldType.IsValueType AndAlso _
|
|
Not Attribute.IsDefined(field, GetType(NotUndoableAttribute)) Then
|
|
' it's a ref type, so check for ISerializationNotification
|
|
Dim value As Object = field.GetValue(Me)
|
|
If TypeOf value Is Serialization.ISerializationNotification Then
|
|
DirectCast(value, Serialization.ISerializationNotification).Deserialized()
|
|
End If
|
|
End If
|
|
Next
|
|
|
|
End Sub
|
|
|
|
''' <summary>
|
|
''' This method is called on the original instance of the
|
|
''' object after it has been serialized.
|
|
''' </summary>
|
|
Protected Overridable Sub Serialized() _
|
|
Implements CSLA.Serialization.ISerializationNotification.Serialized
|
|
|
|
' cascade the call to all child objects/collections
|
|
Dim fields() As FieldInfo
|
|
Dim field As FieldInfo
|
|
|
|
' get the list of fields in this type
|
|
fields = Me.GetType.GetFields( _
|
|
BindingFlags.NonPublic Or _
|
|
BindingFlags.Instance Or _
|
|
BindingFlags.Public)
|
|
|
|
For Each field In fields
|
|
If Not field.FieldType.IsValueType AndAlso _
|
|
Not Attribute.IsDefined(field, GetType(NotUndoableAttribute)) Then
|
|
' it's a ref type, so check for ISerializationNotification
|
|
Dim value As Object = field.GetValue(Me)
|
|
If TypeOf value Is Serialization.ISerializationNotification Then
|
|
DirectCast(value, Serialization.ISerializationNotification).Serialized()
|
|
End If
|
|
End If
|
|
Next
|
|
|
|
End Sub
|
|
|
|
''' <summary>
|
|
''' This method is called before an object is serialized.
|
|
''' </summary>
|
|
Protected Overridable Sub Serializing() _
|
|
Implements CSLA.Serialization.ISerializationNotification.Serializing
|
|
|
|
' cascade the call to all child objects/collections
|
|
Dim fields() As FieldInfo
|
|
Dim field As FieldInfo
|
|
|
|
' get the list of fields in this type
|
|
fields = Me.GetType.GetFields( _
|
|
BindingFlags.NonPublic Or _
|
|
BindingFlags.Instance Or _
|
|
BindingFlags.Public)
|
|
|
|
For Each field In fields
|
|
If Not field.FieldType.IsValueType AndAlso _
|
|
Not Attribute.IsDefined(field, GetType(NotUndoableAttribute)) Then
|
|
' it's a ref type, so check for ISerializationNotification
|
|
Dim value As Object = field.GetValue(Me)
|
|
If TypeOf value Is Serialization.ISerializationNotification Then
|
|
DirectCast(value, Serialization.ISerializationNotification).Serializing()
|
|
End If
|
|
End If
|
|
Next
|
|
|
|
End Sub
|
|
|
|
#End Region
|
|
|
|
End Class
|