Index: Source/Entities/EntityData.cst
===================================================================
--- Source/Entities/EntityData.cst (revision 528)
+++ Source/Entities/EntityData.cst (working copy)
@@ -30,7 +30,7 @@
///
[EditorBrowsable(EditorBrowsableState.Never)]
[Serializable]
- internal protected class <%=structName%> : ICloneable
+ internal protected class <%=structName%> : ICloneable, ICloneableEx
{
#region Variable Declarations
private EntityState currentEntityState = EntityState.Added;
@@ -189,6 +189,81 @@
return _tmp;
}
+ ///
+ /// Creates a new object that is a copy of the current instance.
+ ///
+ /// A new object that is a copy of this instance.
+ public object Clone(IDictionary existingCopies)
+ {
+ if (existingCopies == null)
+ existingCopies = new Hashtable();
+
+ <%=structName%> _tmp = new <%=structName%>();
+
+ <% for(int i=0; i
+ _tmp.<%=GetPropertyName(SourceTable.PrimaryKey.MemberColumns[i])%> = this.<%=GetPropertyName(SourceTable.PrimaryKey.MemberColumns[i])%>;
+ <% if (!IsIdentityColumn(SourceTable.PrimaryKey.MemberColumns[i]) && !(IsComputed(SourceTable.PrimaryKey.MemberColumns[i]))) {%>
+ _tmp.<%=GetOriginalPropertyName(SourceTable.PrimaryKey.MemberColumns[i])%> = this.<%=GetOriginalPropertyName(SourceTable.PrimaryKey.MemberColumns[i])%>;
+ <% } %>
+ <% } %>
+
+ <% for (int x=0; x < SourceTable.NonPrimaryKeyColumns.Count; x++) { %>
+ _tmp.<%= GetPropertyName(SourceTable.NonPrimaryKeyColumns[x]) %> = this.<%= GetPropertyName(SourceTable.NonPrimaryKeyColumns[x]) %>;
+ <% } %>
+
+ #region Source Parent Composite Entities
+ <% if (IncludeGetListByFK) { %>
+ <% //Generate a Source property for each foreign key relation
+ System.Collections.ArrayList filled = new System.Collections.ArrayList();
+ foreach(TableKeySchema tableKey in SourceTable.ForeignKeys)
+ {
+ // related table must be in the selection
+ if (SourceTables.Contains(tableKey.PrimaryKeyTable)) {
+ string fkPropertyName = GetKeysName(tableKey.ForeignKeyMemberColumns);
+
+ if(filled.Contains(fkPropertyName))
+ continue;
+
+ filled.Add(fkPropertyName);
+
+ string pkClassName = GetClassName(tableKey.PrimaryKeyTable.Name);
+
+ %>
+ if (this.<%=fkPropertyName%>Source != null && existingCopies.Contains(this.<%=fkPropertyName%>Source))
+ _tmp.<%=fkPropertyName%>Source = existingCopies[this.<%=fkPropertyName%>Source] as <%= pkClassName %>;
+ else
+ _tmp.<%=fkPropertyName%>Source = MakeCopyOf(this.<%=fkPropertyName%>Source, existingCopies) as <%= pkClassName %>;
+ <% } //end if in SourceTables
+ } //end for each FK
+ }// IncludeGetListByFK%>
+ #endregion
+
+ #region Child Collections
+ <% if (IncludeRelations){
+ int ctr = 0;
+ foreach(CollectionInfo item in GetChildrenCollections(SourceTable, SourceTables).Values) {
+ if (ctr == 0)
+ Response.Write("\t\t\t//deep copy nested objects" + Environment.NewLine);
+ ctr++;
+
+ string typeName = "";
+ if (item.CollectionRelationshipType == MoM.Templates.CommonSqlCode.RelationshipType.OneToOne)
+ typeName = item.TypeName;
+ else
+ typeName = item.CollectionTypeName;
+ %>
+ _tmp.<%= item.PropertyNameUnique %> = (<%= typeName %>) MakeCopyOf(this.<%=item.PropertyNameUnique %>, existingCopies);
+ <% }//end foreach CollectionInfo
+ }//end if IncludeRelations
+ %>
+ #endregion Child Collections
+
+ //EntityState
+ _tmp.EntityState = this.EntityState;
+
+ return _tmp;
+ }
+
#endregion Clone Method
///
Index: Source/Entities/EntityInstanceBase.generated.cst
===================================================================
--- Source/Entities/EntityInstanceBase.generated.cst (revision 528)
+++ Source/Entities/EntityInstanceBase.generated.cst (working copy)
@@ -91,7 +91,7 @@
<% } %>
[Serializable, DataObject]
[CLSCompliant(true)]
- public abstract partial class <%=abstractClassName%> : EntityBase, <%=NameSpace%>.I<%= className %>, IEntityId<<%= keyClassName %>>, System.IComparable, System.ICloneable, IEditableObject, IComponent, INotifyPropertyChanged
+ public abstract partial class <%=abstractClassName%> : EntityBase, <%=NameSpace%>.I<%= className %>, IEntityId<<%= keyClassName %>>, System.IComparable, System.ICloneable, ICloneableEx, IEditableObject, IComponent, INotifyPropertyChanged
{
#region Variable Declarations
@@ -519,37 +519,47 @@
///
/// Returns a Typed <%=className%> Entity
///
- public virtual <%=className%> Copy()
+ protected virtual <%=className%> Copy(IDictionary existingCopies)
{
+ if (existingCopies == null)
+ {
+ // This is the root of the tree to be copied!
+ existingCopies = new Hashtable();
+ }
+
//shallow copy entity
<%=className%> copy = new <%=className%>();
+ existingCopies.Add(this, copy);
copy.SuppressEntityEvents = true;
<% for (int x=0; x < cols.Count; x++) { %>
- copy.<%= GetPropertyName(cols[x]) %> = this.<%= GetPropertyName(cols[x]) %>;
- <% if( cols[x].IsPrimaryKeyMember && !IsIdentityColumn(cols[x]) && !IsComputed(cols[x]) ) { %>
- copy.<%= GetOriginalPropertyName(cols[x]) %> = this.<%= GetOriginalPropertyName(cols[x]) %>;
+ copy.<%= GetPropertyName(cols[x]) %> = this.<%= GetPropertyName(cols[x]) %>;
+ <% if( cols[x].IsPrimaryKeyMember && !IsIdentityColumn(cols[x]) && !IsComputed(cols[x]) ) { %>
+ copy.<%= GetOriginalPropertyName(cols[x]) %> = this.<%= GetOriginalPropertyName(cols[x]) %>;
+ <% } %>
<% } %>
- <% } %>
<% if (IncludeGetListByFK) { %>
- <% //Generate a Source property for each foreign key relation
- System.Collections.ArrayList filled = new System.Collections.ArrayList();
- foreach(TableKeySchema tableKey in SourceTable.ForeignKeys)
- {
- // related table must be in the selection
- if (SourceTables.Contains(tableKey.PrimaryKeyTable)) {
- string fkPropertyName = GetKeysName(tableKey.ForeignKeyMemberColumns);
+ <% //Generate a Source property for each foreign key relation
+ System.Collections.ArrayList filled = new System.Collections.ArrayList();
+ foreach(TableKeySchema tableKey in SourceTable.ForeignKeys)
+ {
+ // related table must be in the selection
+ if (SourceTables.Contains(tableKey.PrimaryKeyTable)) {
+ string fkPropertyName = GetKeysName(tableKey.ForeignKeyMemberColumns);
- if(filled.Contains(fkPropertyName))
- continue;
+ if(filled.Contains(fkPropertyName))
+ continue;
+
+ filled.Add(fkPropertyName);
- filled.Add(fkPropertyName);
-
- string pkClassName = GetClassName(tableKey.PrimaryKeyTable.Name);
- %>
- copy.<%=fkPropertyName%>Source = MakeCopyOf(this.<%=fkPropertyName%>Source) as <%= pkClassName %>;
- <% } //end if in SourceTables
- } //end for each FK
+ string pkClassName = GetClassName(tableKey.PrimaryKeyTable.Name);
+ %>
+ if (this.<%=fkPropertyName%>Source != null && existingCopies.Contains(this.<%=fkPropertyName%>Source))
+ copy.<%=fkPropertyName%>Source = existingCopies[this.<%=fkPropertyName%>Source] as <%= pkClassName %>;
+ else
+ copy.<%=fkPropertyName%>Source = MakeCopyOf(this.<%=fkPropertyName%>Source, existingCopies) as <%= pkClassName %>;
+ <% } //end if in SourceTables
+ } //end for each FK
}// IncludeGetListByFK%>
<%
@@ -566,13 +576,23 @@
else
typeName = item.CollectionTypeName;
%>
- copy.<%= item.PropertyNameUnique %> = (<%= typeName %>) MakeCopyOf(this.<%=item.PropertyNameUnique %>);
+ copy.<%= item.PropertyNameUnique %> = (<%= typeName %>) MakeCopyOf(this.<%=item.PropertyNameUnique %>, existingCopies);
<% }//end foreach CollectionInfo
}//end if IncludeRelations
%>
copy.EntityState = this.EntityState;
copy.SuppressEntityEvents = false;
return copy;
+ }
+
+
+
+ ///
+ /// Returns a Typed <%=className%> Entity
+ ///
+ public virtual <%=className%> Copy()
+ {
+ return this.Copy(null);
}
///
@@ -580,10 +600,18 @@
///
public object Clone()
{
- return this.Copy();
+ return this.Copy(null);
}
///
+ /// ICloneableEx.Clone() Member, returns the Shallow Copy of this entity.
+ ///
+ public object Clone(IDictionary existingCopies)
+ {
+ return this.Copy(existingCopies);
+ }
+
+ ///
/// Returns a deep copy of the child collection object passed in.
///
public static object MakeCopyOf(object x)
@@ -601,6 +629,29 @@
}
///
+ /// Returns a deep copy of the child collection object passed in.
+ ///
+ public static object MakeCopyOf(object x, IDictionary existingCopies)
+ {
+ if (x == null)
+ return null;
+
+ if (x is ICloneableEx)
+ {
+ // Return a deep copy of the object
+ return ((ICloneableEx)x).Clone(existingCopies);
+ }
+ else if (x is ICloneable)
+ {
+ // Return a deep copy of the object
+ return ((ICloneable)x).Clone();
+ }
+ else
+ throw new System.NotSupportedException("Object Does Not Implement the ICloneable or IClonableEx Interface.");
+ }
+
+
+ ///
/// Returns a Typed <%=className%> Entity which is a deep copy of the current entity.
///
public virtual <%=className%> DeepCopy()
@@ -685,7 +736,11 @@
///true if Object1 is a and has the same value as this instance; otherwise, false.
public override bool Equals(object Object1)
{
- return Equals(this, (<%=abstractClassName%>)Object1);
+ // Cast exception if Object1 is null or DbNull
+ if (Object1 == null || Object1 == DBNull.Value)
+ return false;
+ else
+ return Equals(this, (<%=abstractClassName%>)Object1);
}
///
Index: Source/Entities/IEntity.cst
===================================================================
--- Source/Entities/IEntity.cst (revision 528)
+++ Source/Entities/IEntity.cst (working copy)
@@ -20,6 +20,7 @@
%>
using System;
using System.ComponentModel;
+using System.Collections;
namespace <%=NameSpace%>
{
@@ -140,4 +141,17 @@
///
string EntityTrackingKey { get; set; }
}
+
+ ///
+ /// Interface that TList and every entity implements to support
+ /// cloning of an object tree.
+ ///
+ public interface ICloneableEx
+ {
+ ///
+ /// The tracking key used to with the
+ ///
+ ///A list containing references to all objects already copied.
+ object Clone(IDictionary existingCopies);
+ }
}
Index: Source/Entities/ListBase.cst
===================================================================
--- Source/Entities/ListBase.cst (revision 528)
+++ Source/Entities/ListBase.cst (working copy)
@@ -26,7 +26,7 @@
/// Supports filtering, databinding, searching and sorting.
///
[Serializable]
- public abstract class ListBase : BindingList, IBindingListView, IBindingList, IList, ICloneable, IListSource, ITypedList, IDisposable, IComponent, IRaiseItemChangedEvents, IDeserializationCallback
+ public abstract class ListBase : BindingList, IBindingListView, IBindingList, IList, ICloneable, ICloneableEx, IListSource, ITypedList, IDisposable, IComponent, IRaiseItemChangedEvents, IDeserializationCallback
{
private List _OriginalList = new List();
@@ -578,6 +578,15 @@
}
///
+ /// Creates an exact copy of this instance.
+ ///
+ ///
+ public virtual object Clone(IDictionary existingCopies)
+ {
+ throw new NotImplementedException("Method not implemented.");
+ }
+
+ ///
/// Creates an exact copy of this TList{T} object.
///
///A new, identical copy of the TList{T} casted as object.
@@ -594,7 +603,31 @@
System.NotSupportedException("object not cloneable");
}
}
- #endregion ICloneable
+
+ ///
+ /// Creates an exact copy of this TList{T} object.
+ ///
+ ///A new, identical copy of the TList{T} casted as object.
+ public static object MakeCopyOf(object x, IDictionary existingCopies)
+ {
+ if (x is ICloneableEx)
+ {
+ // Return a deep copy of the object
+ return ((ICloneableEx)x).Clone(existingCopies);
+ }
+ else if (x is ICloneable)
+ {
+ // Return a deep copy of the object
+ return ((ICloneable)x).Clone();
+ }
+ else
+ {
+ throw new
+ System.NotSupportedException("object not cloneable");
+ }
+ }
+
+ #endregion ICloneable
#region PropertyCollection
///
Index: Source/Entities/TList.cst
===================================================================
--- Source/Entities/TList.cst (revision 528)
+++ Source/Entities/TList.cst (working copy)
@@ -119,8 +119,18 @@
///
public override object Clone()
{
- return this.Copy();
+ return this.Copy(null);
}
+
+ ///
+ /// Creates an exact copy of this TList{T} instance.
+ ///
+ ///The TList{T} object this method creates, cast as an object.
+ ///
+ public override object Clone(IDictionary existingCopies)
+ {
+ return this.Copy(existingCopies);
+ }
///
/// Creates an exact copy of this TList{T} object.
@@ -128,10 +138,26 @@
///A new, identical copy of the TList{T}.
public virtual TList Copy()
{
+ return this.Copy(null);
+ }
+
+ ///
+ /// Creates an exact copy of this TList{T} object.
+ ///
+ ///A new, identical copy of the TList{T}.
+ public virtual TList Copy(IDictionary existingCopies)
+ {
+ if (existingCopies == null)
+ existingCopies = new Hashtable();
+
TList copy = new TList();
foreach (T item in this)
{
- T itemCopy = (T)MakeCopyOf(item);
+ T itemCopy = default(T);
+ if (existingCopies.Contains(item))
+ itemCopy = (T)existingCopies[item];
+ else
+ itemCopy = (T)MakeCopyOf(item, existingCopies);
copy.Add(itemCopy);
}