Full Clone Source

Posts   
 
    
ianvink
User
Posts: 394
Joined: 15-Dec-2006
# Posted on: 26-Jun-2007 19:28:53   

Borrowed from http://dotnet.org.za/danieb/archive/2006/09/21/60832.aspx the cloner


using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using SD.LLBLGen.Pro.ORMSupportClasses;

namespace LLBLisSuchANiceTool.Core.Helpers
{
    /// <summary>
    /// Clone support for LLBL generated object
    /// </summary>
    public class Cloner
    {
        /// <summary>
        /// Sets the entity dirty.
        /// </summary>
        /// <param name="entity">The entity.</param>
        public static void SetEntityDirty(IEntity entity)
        {
            entity.IsDirty = true;
            entity.IsNew = true;
            for (int i = 0; i < entity.Fields.Count; i++)
            {
                //don't mark the primary-keys and timestamps (DbType 19) as changed
                if (!entity.Fields[i].IsPrimaryKey && entity.Fields[i].SourceColumnDbType != 19)
                {
                    entity.Fields[i].IsChanged = true;
                    if (entity.Fields[i].IsNull)
                    {
                        //reset Null fields
                        entity.SetNewFieldValue(i, null);
                    }
                }
            }
        }

        /// <summary>
        /// Clones an object by using the
        /// <see cref="BinaryFormatter" />.
        /// </summary>
        /// <typeparam name="T">Type of the object
        /// (The object to be cloned must be serializable.)
        /// </typeparam>
        /// <param name="obj">The object to clone.</param>
        /// <returns>Cloned Object</returns>
        public static T SerializationClone<T>(T obj) where T : class, ISerializable
        {
            using (MemoryStream buffer = new MemoryStream())
            {
                BinaryFormatter formatter = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.Clone));
                formatter.Serialize(buffer, obj);
                buffer.Position = 0;
                return (T)formatter.Deserialize(buffer);
            }
        }

    }
}

MatthewM
User
Posts: 78
Joined: 26-Jul-2006
# Posted on: 26-Jun-2007 22:20:22   

I've posted this before, and I don't mean to show up another's work, however I wanted to add the graph clone impl I use:

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using SD.LLBLGen.Pro.ORMSupportClasses;

namespace NS
{
    /// <summary>
    /// For cloning an Entity and all related entities, ie the whole graph
    /// </summary>
    public class CloneHelper
    {
        private CloneHelper()
        {
        }

        private static object CloneObject(object o)
        {
            object oOut;
            lock (o)
            {
                MemoryStream ms = new MemoryStream();
                BinaryFormatter bf = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.Clone));
                bf.Serialize(ms, o);
                ms.Seek(0, SeekOrigin.Begin);
                oOut = bf.Deserialize(ms);
                ms.Close();
            }
            return oOut;
        }

        private static void ResetEntityAsNew(IEntity Entity)
        {
            Entity.IsNew = true;
            Entity.IsDirty = true;
            Entity.Fields.IsDirty = true;
            for (int f = 0; f < Entity.Fields.Count; f++)
            {
                Entity.Fields[f].IsChanged = true;
            }
        }

        public static IEntity CloneEntity(IEntity Entity, bool ResetAsNew)
        {
            IEntity newEntity;

            newEntity = (IEntity)CloneObject(Entity);
            ObjectGraphUtils ogu = new ObjectGraphUtils();
            List<IEntity> flatList = ogu.ProduceTopologyOrderedList(newEntity);

            if (ResetAsNew)
                for (int f = 0; f < flatList.Count; f++)
                    ResetEntityAsNew(flatList[f]);

            return newEntity;
        }

        public static IEntity CloneEntity(IEntity Entity)
        {
            return CloneEntity(Entity, true);
        }

        public static T CloneEntity2<T>(T Entity)
            where T : EntityBase
        {
            return (T)CloneEntity(Entity, true);
        }

        public static T CloneEntity2<T>(T Entity, bool ResetAsNew)
            where T : EntityBase
        {
            return (T)CloneEntity(Entity, ResetAsNew);
        }
    }
}

JayBee
User
Posts: 282
Joined: 28-Dec-2006
# Posted on: 19-Oct-2007 20:33:33   

Hi Matthew,

Suppose I have the following datastructure:

Grandparent - Parent - Child

and I want to clone the Parent.

What should I do to clone the Parent and Child entities but not the GrandParent entities?

Jan

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39910
Joined: 17-Aug-2003
# Posted on: 21-Oct-2007 11:31:22   

Use a loop and produce individual clones. Using the serialization trick creates a clone of the whole graph.

Frans Bouma | Lead developer LLBLGen Pro
JayBee
User
Posts: 282
Joined: 28-Dec-2006
# Posted on: 24-Oct-2007 23:35:33   

I nullified the reference in the parent to the grandparent and than cloned the parent and related entities.

Works fine.

Jan