深入解析SharePoint Content Deployment and Migration API 之三
提供一些真实的import的例子
==========================
我们第二部分了解了export之后, 我们现在来集中注意力到import的部分. 实际上Import有两种不同的工作方式:
-
Import对象并保存对象的identity和location
-
Import对象, 但不保存对象的identity
第一种方式被用在管理中心站点页面的Content Deployment功能中. 第二种方式是用在STSADM -o import 中的, 还用在Site Manager中的Copy/Move 操作里.
第一种方式与在CMS2002中使用的import方法一样: import 的对象会拥有与在源系统中一样的GUID.
第二种方式, 从另一方面, 允许我们import到site collection hierarchy的不同地方, 所以可以用在copy操作上.
为了论证Content Deployment and Migration API是多么强大, 在这里我会再一次地提供一些例子:
-
保留对象identity的import
-
在import的过程中修改掉imported对象的parent.
下面的例子假设目标站点集在相同服务器的2001端口上.
1) Import with preserving the object identity
----------------------------------------------------------
这个方法的一个预备条件是, 所有imported对象的parents需要已经在目标数据库中已经存在了. 所以不可能使用这个方法把对象import到一个具有不同结构的站点中. 通常, 它意味着你可以使用经典的staging secnarios, 在那里你有一个authoring farm, 一个staging farm, 和一个production farm. 内容已经初始地在authoring farm中创建了, 并已经被部署到了staging farm.
对于这种方法, package是仅包含一个单独的列表项, 还是一个站点, 或者市一个整个的站点集都无所谓. 是否是使用incremental deployment 还是full deployment也无关紧要. 因为所有package中的对象的parents都已经在目标数据库中存在了, import 引擎会正确地import这些items.
如果你有不同的站点集, 并且需要在他们之间交换数据(比方说, 从一个站点集http://www.company1.com/中拷贝一个文档库, 到站点集http://www.company2.com/中, 那么你需要使用不保存对象identity的方法)
SPImportSettings settings = new SPImportSettings(); settings.SiteUrl = "http://localhost:2001"; settings.FileLocation = @"c:\export"; settings.FileCompression = false; settings.RetainObjectIdentity = true; SPImport import = new SPImport(settings); import.Run();
跟export过程相似, 我们首先创建一个对象, 并配置import. 这可以通过SPImportSettings 来完成.
下面是关于我在import中使用的配置的简短解释:=
-
SiteUrl - 这就是Import过程要使用的目的站点集的URL地址.
-
FileLocation - 这就是保存需要被import的数据的文件夹的位置.
-
FileCompression - 这个属性定义了exported的数据是否使用了压缩格式.
-
RetainObjectIdentity - 这个属性定义了是否在import的过程中要保存对象的identity. 如果这个值是true, 那么对象的identity就会被保留下来. 意味着imported的items的GUID和URL会和exporting server的是一样的. 注意, 这意味着所有imported的对象的parent objects必须已经在目标的数据库中存在并可用. 如果这个值是false, 那么对象们会在import的过程中得到一个新生成的Guid, 还有, 它还有可能在import过程中控制imported的root objects. 我们稍后讨论.
2) Change the Parent of the imported objects during Import
----------------------------------------------------------
让我们假设我们使用part 2中的第三点的方法, 从源站点集已经exported了一个列表. 现在我们想要import一个列表到目标站点集中的一个不同的站点上. 目标站点集是否与源站点集相同无关紧要, 目标站点集于源站点集是否是在同一个database中也不重要. 目标站点集是否与源站点集在同一个farm也不重要.
如果你从一个数据库中export了一个item(比方说一个列表), 而没export它的parent, 那么这个exported item就会在包中称为orphaned(孤儿). 一个包中可以包含多个不同的orphaned对象(比如说你export了多个不同的列表或者列表项).
Import方法允许我们为每一个export package中的orphaned的对象定义一个新的parent. 意味着如果你选择了export web A 和 web B, 其中B是A的子站点, 那么你仅能修改web A的parent. web B的parent永远都会是web A, 因为web B在export package中不是orphaned.
There are actually two methods that can be used to assign a new parent to orphaned objects:
实际上有两种方法可以用来assign新的parent给orphaned的对象:
第一种方法- 所有orphaned的对象都应该被import到相同的子站点下
如果所有的items都需要被添加到相同子站点的时候, 这种方法比较适合. 比如说: 如果你export了几个列表和文档库(或者是从其他源站点来的列表和文档库), 现在你想把它们添加到相同的子站点下.
SPImportSettings settings = new SPImportSettings(); settings.SiteUrl = "http://localhost:2001"; settings.WebUrl = "http://localhost:2001/MyDestWeb"; settings.FileLocation = @"c:\export"; settings.FileCompression = false; settings.RetainObjectIdentity = false; SPImport import = new SPImport(settings); import.Run();
要使得这个可以正常工作, 需要两个非常重要的配置:
-
WebUrl - 这个属性定义了export package中的所有orphaned对象的parent web. 如果package中包含了orphaned的文档, 那么这个方法不能被使用, 因为站点不能作为文档的parent. 文档的parent要么应该是列表, 要么就应该是文件夹.
-
RetainObjectIdentity - 这个属性定义了是否要保存对象的identity. 如果值为false, 那么对象将会得到一个新生成的Guid, 并且他可以在为imported的orphaned的对象指定parent时使用.
第二种方法- 为每一个orphaned的对象指配一个单独的parent.
这个方法比第一个要灵活一些, 但是也需要更多的代码. 这里, 在import process已经从import package中收集好了orphaned的对象的列表之后, 它需要拦截住import的进程, 来指配一个新的parent给每一个orphaned的对象.
可以通过一个自定义的event handler来完成这一点:
static void OnImportStarted(object sender, SPDeploymentEventArgs args) { SPSite site = new SPSite("http://localhost:2001"); SPWeb web = site.RootWeb; SPImportObjectCollection rootObjects = args.RootObjects; foreach (SPImportObject io in rootObjects) { io.TargetParentUrl = web.Url; } web.dispose(); site.dispose(); }
上面的event handler为所有的orphaned的对象进行了一个"re-parenting"的工作, orphaned的对象是event参数中的RootObjects集合中的对象. 上面的例子中, 我们实际上做的与第一种方法中的事情是一样的, 我们为所有的对象指配了而一个固定的web作为parent. 但是, 你可以很容易地在event handler中扩展这个逻辑, 为不同类型的对象指配不同的parent:
static void OnImportStarted(object sender, SPDeploymentEventArgs args) { SPSite site = new SPSite("http://localhost:2001"); SPWeb web = site.RootWeb; SPList list = web.Lists["MyDocLib"]; SPImportObjectCollection rootObjects = args.RootObjects; foreach (SPImportObject io in rootObjects) { if (io.Type == SPDeploymentObjectType.ListItem) { io.TargetParentUrl = list.RootFolder.ServerRelativeUrl; } if (io.Type == SPDeploymentObjectType.List) { io.TargetParentUrl = web.Url; } ... } web.dispose(); site.dispose(); }
正如你看到的, eventhandler可以被很轻松地扩展. 除了看object type以外, 你还可以查看原始的TargetParentUrl 来确定原来是放在哪里的, 然后把这个信息融入到你的"分配"逻辑中去. 现在我们需要看一下如何能把这个event handler与import process 挂钩起来. 可以这样做:
static void ImportDocLibItem() { SPImportSettings settings = new SPImportSettings(); settings.SiteUrl = "http://localhost:2001"; settings.FileLocation = @"c:\deployment5"; settings.FileCompression = false; settings.RetainObjectIdentity = false; SPImport import = new SPImport(settings); EventHandler<SPDeploymentEventArgs> eventHandler = new EventHandler<SPDeploymentEventArgs>(OnImportStarted); import.Started += eventHandler; import.Run(); }
正如你看到的, 你需要在开启import process之前, 注册event handler到import class上.
有好几个event handlers可以被注册到import上, MSDN上有更多更详细的信息:
http://msdn2.microsoft.com/en-us/library/microsoft.sharepoint.deployment.spimport_events.aspx
相似地, 如果需要的话一些event也可以被注册到export上:
http://msdn2.microsoft.com/en-us/library/microsoft.sharepoint.deployment.spexport_events.aspx
3) Importing using compression
--------------------------------------------------------
当使用压缩选项的时候, SPImportSettings 对象的一些其他设定需要跟随着进行调整:
SPExportSettings settings = new SPExportSettings(); settings.FileLocation = @"c:\export"; settings.FileCompression = true; settings.BaseFileName = "ExportedItems.cmp";
这里是关于一些属性的解释:
-
FileCompression - 指定了内容是否是以压缩的CAB文件提供过的, 还是未压缩的.
-
FileLocation - 这个属性定义了在哪里存放export了的文件. 如果使用了压缩, 那么它就定义了生成的压缩的content migration pack(CMP)文件的包位置了.
-
BaseFileName - 这个属性仅在开启了压缩的时候才用得上. 它定义了压缩了的content migration pack 文件的名字. 默认的后缀(如果没有指定的话), 是"cmp". 如果超过了文件尺寸的最大值, 一个新的文件会在BaseFileName 的基础上生成, 后面带一个整形数值. 举个例子: 根据上面的配置, 下一个文件应该是ExportedItems1.cmp
第四部分将会介绍一些具体的secnarios, 在move的场景下调整链接啦. 比如说, 一个图片被移动到一个新位置, 你想要调整所有引用到这份图片的页面的链接.
摘译自:
Deep Dive into the SharePoint Content Deployment and Migration API - Part 4