Quantcast
Viewing all articles
Browse latest Browse all 7205

How to clone a persistent object

This is an example for the How to clone a persistent object Knowledge Base article. Please refer to the article for the explanation.

Question Comments

Added By: Sigurd Decroos at: 1/8/2013 5:48:41 PM    

There's a little catch with this code. Primary Keys are changed, so it doesn't make a real clone, but a copy. You have to change the code a bit so the primary key gets synced too if needed.

Added By: Mr292 at: 2/16/2013 12:45:27 PM    

I refactored some in order to replicate to different databases as well as to different assemblies in the other database. I came about this requirement because I wanted to remodel my DOM and did not want to have to manually do a lot of data imports.

    public class CloneIXPSimpleObjectHelper
    {
        /// <summary>
        /// A dictionary containing objects from the source session as key and objects from the
        /// target session as values
        /// </summary>
        /// <returns></returns>
        Dictionary<object, object> clonedObjects;
        Session sourceSession;
        UnitOfWork targetSession;

        /// <summary>
        /// Initializes a new instance of the CloneIXPSimpleObjectHelper class.
        /// </summary>
        public CloneIXPSimpleObjectHelper(Session source, UnitOfWork target)
        {
            clonedObjects = new Dictionary<object, object>();
            sourceSession = source;
            targetSession = target;
        }

        /// <summary>
        /// Initializes a new instance of the CloneIXPSimpleObjectHelper class to Clone to Different DB.
        /// </summary>
        public CloneIXPSimpleObjectHelper(Session session, string connstring)
        {
            UnitOfWork NewUOW = new UnitOfWork(
                XpoDefault.GetDataLayer(connstring, DevExpress.Xpo.DB.AutoCreateOption.SchemaAlreadyExists));

            clonedObjects = new Dictionary<object, object>();
            sourceSession = session;
            targetSession = NewUOW;
        }

        /// <summary>
        /// Initializes a new instance of the CloneIXPSimpleObjectHelper class to Clone to Different Assembly / DB.
        /// </summary>
        public CloneIXPSimpleObjectHelper(Session session, string connstring, System.Reflection.Assembly assembly)
        {

            var dict = new ReflectionDictionary();
            foreach (var item in assembly.GetTypes())
            {
                    if (item.IsSubclassOf(typeof(XPBaseObject)))
                        dict.CollectClassInfos(item);
            }
    
            UnitOfWork NewUOW = new UnitOfWork(
                XpoDefault.GetDataLayer(connstring, dict,
                DevExpress.Xpo.DB.AutoCreateOption.SchemaAlreadyExists));

            clonedObjects = new Dictionary<object, object>();
            sourceSession = session;
            targetSession = NewUOW;

        }

        public void Commit()
        {
            targetSession.CommitTransaction();
           
        }

        public T Clone<T>(T source) where T : IXPSimpleObject
        {
            return Clone<T>(source, targetSession, CloneMethod.IgnoreIfExistsInDesitnation);
        }
        public T Clone<T>(T source, CloneMethod sync) where T : IXPSimpleObject
        {
            return (T)Clone(source as IXPSimpleObject, targetSession, sync);
        }

        public object Clone(IXPSimpleObject source)
        {
            return Clone(source, targetSession, CloneMethod.IgnoreIfExistsInDesitnation);
        }
        public object Clone(IXPSimpleObject source, CloneMethod sync)
        {
            return Clone(source as IXPSimpleObject, targetSession, sync);
        }
        public object Clone(IXPSimpleObject source, Session targetSession, CloneMethod sync)
        {
            return Clone(source as IXPSimpleObject, targetSession, sync);
        }
        public T Clone<T>(T source, UnitOfWork targetSession, CloneMethod sync) where T : IXPSimpleObject
        {
            return (T)Clone(source as IXPSimpleObject, targetSession, sync);
        }
        public object Clone(XPBaseObject obj, Type targetType, CloneMethod sync)
        {
            return Clone(obj, targetSession, targetSession.GetClassInfo(targetType), sync);
        }

        public enum CloneMethod
        {
            TransferOnly,
            Synchronize,
            IgnoreIfExistsInDesitnation
        }
     /// <summary>
        /// Clones and / or synchronizes the given IXPSimpleObject.
        /// </summary>
        /// <param name="source"></param>
        /// <param name="targetSession"></param>
        /// <param name="synchronize">If set to true, reference properties are only cloned in case
        /// the reference object does not exist in the targetsession. Otherwise the exising object will be
        /// reused and synchronized with the source. Set this property to false when knowing at forehand
        /// that the targetSession will not contain any of the objects of the source.</param>
        /// <returns></returns>
        public object Clone(IXPSimpleObject source, UnitOfWork parentSession, XPClassInfo cloneClassInfo, CloneMethod sync)
        {
            if (source == null)
                return null;

            object sourceKey = source.Session.GetKeyValue(source);

            if (clonedObjects.ContainsKey(source))
                return parentSession.GetObjectByKey(cloneClassInfo,cloneClassInfo.KeyProperty.GetValue(clonedObjects[source]));

            
            NestedUnitOfWork nestedSession = parentSession.BeginNestedUnitOfWork();
            IXPSimpleObject clone = null;

            if (sync != CloneMethod.TransferOnly)
            {
                clone = (IXPSimpleObject)nestedSession.GetObjectByKey(cloneClassInfo, sourceKey);
                if (clone != null)
                {
                    if (sync == CloneMethod.IgnoreIfExistsInDesitnation)
                    {
                        clonedObjects.Add(source, clone);
                        return nestedSession.GetParentObject(clone);
                    }
                }
            }

            if (clone == null)
                clone = (IXPSimpleObject)cloneClassInfo.CreateNewObject(nestedSession);
      
            clonedObjects.Add(source, clone);

            try
            {
                XPClassInfo sourceClassInfo = source.Session.GetClassInfo(source.GetType());
                if (sourceClassInfo.KeyProperty.GetType() == cloneClassInfo.KeyProperty.GetType())
                    cloneClassInfo.KeyProperty.SetValue(clone, sourceKey);

                foreach (XPMemberInfo cloneMember in cloneClassInfo.PersistentProperties)
                {
                    XPMemberInfo sourceMem = sourceClassInfo.GetMember(cloneMember.Name);

                    if (sourceMem == null
                        || cloneMember is DevExpress.Xpo.Metadata.Helpers.ServiceField
                        || cloneMember.IsKey)
                        continue;

                    object val = null;
   
                    if (cloneMember.ReferenceType != null)
                    {
                        object createdByClone = cloneMember.GetValue(clone);
                        if (createdByClone != null)
                        {
                           
                            val = Clone((IXPSimpleObject)sourceMem.GetValue(source),
                                nestedSession,
                                nestedSession.GetClassInfo(cloneMember.MemberType),
                                sync==CloneMethod.TransferOnly?CloneMethod.Synchronize:sync);
                        }
                        else
                            if ((cloneMember.IsAggregated)
                                //REMOVE Below LINE IF YOU WANT TO MAINTAIN ONLY ONE WAY AGGREGATIOn
                                || (cloneMember.IsAssociation
                                    && cloneMember.GetAssociatedMember().IsAggregated)
                                )
                            {
                                val = Clone((IXPSimpleObject)sourceMem.GetValue(source), nestedSession,
                                       nestedSession.GetClassInfo(cloneMember.MemberType), sync);
                            }

                    }
                    else
                    {
                            val = sourceMem.GetValue(source);
                    }

                    if ((val != null) && !(val is DateTime && (DateTime)val == DateTime.MinValue))
                        cloneMember.SetValue(clone, val);
                }

                foreach (XPMemberInfo m in cloneClassInfo.CollectionProperties)
                {
                    if (m.HasAttribute(typeof(AggregatedAttribute)))
                    {
                        XPBaseCollection col = (XPBaseCollection)m.GetValue(clone);
                        XPBaseCollection colSource = (XPBaseCollection)sourceClassInfo.GetMember(m.Name).GetValue(source);

                        foreach (IXPSimpleObject obj in new ArrayList(colSource))
                        {
                            XPClassInfo targetinfo = col.GetObjectClassInfo();
                            col.BaseAdd(
                                Clone(obj, nestedSession,
                                    targetinfo, sync));
                        }
                    }
                }

                nestedSession.CommitTransaction(); //
                clonedObjects[source]= clone;
                return nestedSession.GetParentObject(clone);
            }
            catch
            {
                if (nestedSession.InTransaction)
                    nestedSession.RollbackTransaction();
            }

            return null;
        }

    
    
    }


Viewing all articles
Browse latest Browse all 7205

Trending Articles