【问题标题】:Deep cloning entity from one org to another从一个组织到另一个组织的深度克隆实体
【发布时间】:2011-12-23 18:13:48
【问题描述】:

所以,手头还有另一个有趣的任务。

我们创建了一个 Windows 服务,以在生产中的 2 个 CRM 2011 组织之间保持一些记录同步。

我们已经研究了我们想要的深度克隆,但它似乎是在深度克隆 EntityReference,而不是实际的 Entity。

任何想法、建议等都会很棒。

【问题讨论】:

    标签: c# .net dynamics-crm dynamics-crm-2011


    【解决方案1】:

    我已成功使用此代码进行深度克隆:

    我使用 XRM 服务上下文,将克隆复制到新实体,删除将其指定为已存在实体的属性(例如主键等)设置与现有实体的关系,然后将其发送到创建方法。我必须对所有相关实体明确地做同样的事情(在我的例子中,我已经为 webfiles 和 notes 做了)

            var clonedwebpage = ((Entity)webpage).Clone(true);
    
            clonedwebpage.Id = Guid.NewGuid();
            clonedwebpage.Attributes.Remove("adx_webpageid");
            //clonedwebpage.Attributes.Remove("adx_pagetemplateid");
            clonedwebpage.EntityState = null;
            clonedwebpage["adx_websiteid"] = new EntityReference("adx_webpage",livesiteGuid);
            //clonedwebpage["adx_parentpageid"] = 
            // create the template guid
            Guid tempGuid = new Guid(templateguid);
            clonedwebpage["adx_pagetemplateid"] = new EntityReference("adx_pagetemplate",tempGuid); // set the template of the new clone
    
    
            //serviceContext.Attach(cloned);
            //serviceContext.MergeOption = MergeOption.NoTracking;
    
            Guid clonedwebpageguid = _service.Create(clonedwebpage);
    
             //var webpage = serviceContext.Adx_webpageSet.Where(wp => wp.Id == webpageguid).First();
            //var notes_webile = serviceContext.Adx_webfileSet.Where(wf => wf.
    
    
    
    
    
    
    
    
            //*********************************** WEB FILE *********************************************
            foreach (var webfile in webpage.adx_webpage_webfile)
            {
                var cloned_webfile = webfile.Clone(); 
    
                //should iterate through every web file that is related to a web page, and clone it. 
                cloned_webfile.Attributes.Remove("adx_webfileid");
                cloned_webfile.Attributes.Remove("adx_websiteid");
                cloned_webfile.Attributes.Remove("adx_parentpageid");
                cloned_webfile["adx_websiteid"] = new EntityReference("adx_website", livesiteGuid);
                cloned_webfile["adx_parentpageid"] = new EntityReference("adx_webpage", clonedwebpageguid);
                cloned_webfile.EntityState = null;
                cloned_webfile.Id = Guid.NewGuid();
                Guid ClonedWebFileGuid = _service.Create(cloned_webfile);
    
                //*********************************** NOTE *********************************************
                foreach (var note in webfile.adx_webfile_Annotations)
                {
    
                    var cloned_note = note.Clone();
    
                    cloned_note.Attributes.Remove("annotationid"); // pk of note
                    cloned_note.Attributes.Remove("objectid"); // set to web file guid
    
                    cloned_note["objectid"] = new EntityReference("adx_webfile", ClonedWebFileGuid); // set the relationship between our newly cloned webfile and the note
                    cloned_note.Id = Guid.NewGuid();
                    cloned_note.EntityState = null;
    
                    Guid clonednote = _service.Create(cloned_note);
    
    
                    //cloned_note.Attributes.Remove("ownerid");
                    //cloned_note.Attributes.Remove("owningbusinessunit");
                    //cloned_note.Attributes.Remove("owningteam");
                    //cloned_note.Attributes.Remove("owninguser");
    
    
                }
    

    【讨论】:

      【解决方案2】:

      我们不将其与动态一起使用,但是当我们需要深拷贝时,我们使用 BinaryFormatter 序列化对象,然后将其反序列化为新对象,这与 .Net 远程处理的情况非常相似。

      这是我们的 VB.Net 解决方案(如果需要,我可以转换为 C#):

      ''' <summary>
      ''' This method clones all of the items and serializable properties of the current collection by 
      ''' serializing the current object to memory, then deserializing it as a new object. This will 
      ''' ensure that all references are cleaned up.
      ''' </summary>
      ''' <returns></returns>
      ''' <remarks></remarks>
      Public Function CreateSerializedCopy(Of T)(ByVal oRecordToCopy As T) As T
          ' Exceptions are handled by the caller
      
          If oRecordToCopy Is Nothing Then
              Return Nothing
          End If
      
          If Not oRecordToCopy.GetType.IsSerializable Then
              Throw New ArgumentException(oRecordToCopy.GetType.ToString & " is not serializable")
          End If
      
          Dim oFormatter As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
      
          Using oStream As IO.MemoryStream = New IO.MemoryStream
              oFormatter.Serialize(oStream, oRecordToCopy)
              oStream.Position = 0
              Return DirectCast(oFormatter.Deserialize(oStream), T)
          End Using
      End Function
      

      【讨论】:

      • 感谢您的回复!序列化/反序列化路线对我来说听起来不错。你能提供任何例子吗?就像您可以告诉它克隆的“深度”以及如何将其从序列化格式导入其他组织一样。谢谢。
      • @JonC:我添加了我们的 VB 代码作为示例。它将序列化整个对象树,但它还将调用每个对象的序列化构造函数和 GetData 方法,因此您有机会根据需要更改信息。由于我们不使用 CRM,因此我并不完全清楚更改组织所涉及的内容,但这是我们用于一般 .net 对象的解决方案。
      猜你喜欢
      • 2019-12-28
      • 1970-01-01
      • 2018-07-07
      • 2018-03-06
      • 2013-11-05
      • 1970-01-01
      • 2013-10-11
      • 1970-01-01
      • 2021-09-19
      相关资源
      最近更新 更多